有没有人愿意加入开源项目db-unifier

wuyue-tiger 2014-05-18 10:12:53
加精
db-unifier
==========

db-unifier是一款基于Java的数据库处理工具集,主要包括三项主要内容:
1、为各类数据库提供统一的对象包装和操作接口
2、通过JDBC的DAO层代码生成器
3、为各种数据库之间的数据导入导出提供高效率的工具
下面对这三项功能进行详细的介绍。

1、为各类数据库提供统一的对象包装和操作接口
这类工具已经很多了,比如大家耳熟能详的Hibernate、iBatis,包括Apache的DBTools、Spring的JdbcTemplate。为什么我们还要推出db-unifier这样一个功能类似的东西呢?
这些工具的主要目的都是对JDBC进行包装,使开发人员能更容易的进行数据库开发,在代码的可读性、性能问题、移植问题上,这些工具都尽量做了权衡,达到了他们认为的完美。
db-unifier是鉴于我们的开发经验和考虑,权衡出来的数据库工具,其主要考虑的方向有以下几点:
1、简洁。所有的核心接口都在一个类里边,这个类是DbUnifier,代码不过1000行,却提供了大量的高质量功能方法。怎么读配置或通过代码来构造DbUnifier对象,都是一目了然的简单。
2、避免数据库连接泄漏的问题。数据库建立连接、关闭连接默认情况下都由db-unifier处理。有人会觉得这样影响效率,当然我们也提供自己手动控制连接的方法,只是默认情况下采用自动的方式。
3、统一的数据库操作类型。在db-unifier中,所有的数据库数据只有五种数据类型,String、Number(BigDecimal)、Timestamp、Clob(String)、Blob(byte[]),经过我们反复测试,我们会例出各种数据库数据类型到这五种类型的映射表,当然我们也有少数的数据类型不能支持,有些是JDBC驱动的问题,有些是我们出于移植的考虑,有些数据库的数据类型在别的数据库里没有对应的数据类型支持,这样的数据类型只能不予支持,幸好这只是极少的一部分。
4、简化了很多复杂的数据库操作。比如:数据库分页,非常简单的接口,而且你不用关心记录总数怎么取,不用考虑各种数据库之间的差异,最关键的是绝对的高效。再比如LOB字段的处理,可以直接通过增、删、改、查等接口处理,遇到较大的LOB,也可以用流的方式处理,避免内存溢出的问题。再比如获取数据库序列,我们采用了统一的算法,不同的数据库都使用同一个接口来获取序列,而且这个方法可以在多线程环境下使用,甚至是集群环境下都没有问题。

2、通过JDBC的DAO层代码生成器
这是一个配合db-unifier的代码生成器,生成基于db-unifier的DAO层类。有了这样类,可以简化开发代码,避免低级的书写错误,使开发者更专注于业务。另外,也可以在此基础上配合一定的代码来防止SQL注入的问题。

3、为各种数据库之间的数据导入导出提供高效率的工具
异构数据库的导入导出一直是个大难题,一般的工具配置复杂,尤其是不支持LOB这样的大字段数据,我们的这个工具不仅配置简单,而且具有以下几个特点。
1、速度非常快,这个因为取决于系统环境,这个只有谁用谁知道了,至少我们是跟别的工具作过比较的。
2、支持LOB字段的导入导出。
3、自动侦测数据库表的主、从关系,保障数据库的导入不受外键约束的影响。
4、根据配置可以选择遇到重复数据时的处理方式————忽略或者中止。

由于需要大量的测试工作,希望找一些志同道合的程序员一起来完善这个开源项目,有兴趣的快来加入
项目地址:https://code.csdn.net/tigeryu/db-unifier
...全文
5089 93 打赏 收藏 转发到动态 举报
写回复
用AI写文章
93 条回复
切换为时间正序
请发表友善的回复…
发表回复
时光机的主人 2014-06-23
  • 打赏
  • 举报
回复
我愿意参与,但是工作中我的电脑是受限访问的,所以只有非常少的时间,还有我也是java刚起步,希望多多关照,谢谢!
小小二子 2014-06-04
  • 打赏
  • 举报
回复
个人觉得不去做的人,没有资格去批判别人的东西。 就像知道你做的这个东西,无论易用性怎么样,至少你去做了。 也不支持,因为类似的东西太多了 也不反对,做了,才能更加深入理解,学到更多东西。
wuyue-tiger 2014-06-04
  • 打赏
  • 举报
回复
引用 91 楼 shine333 的回复:
最后总结下,不能说你这样的设定完全是错的。但是,针对我支出的问题,要么请赶快写出文档,要么,请在运行时做出限定。比如,使用非Connection构造函数时,检查当前运行环境,是否是受到了托管,否则异常。
在没有容器的情况下,需要高效,完全可以通过传入Connection来做,代码如下:

DbSource dbSource = XmlConfig.getDbSource("test");
Connection con = dbSource.getConnection();
try {
	DbUnifier unifier = new DbUnifier(con);
	RowSet rowSet = unifier.executeSelectSql("select * from AAA order by A", 100, 50);
} finally {
	DbUtil.closeConnection(con);
}
shine333 2014-06-04
  • 打赏
  • 举报
回复
引用 89 楼 tigeryu 的回复:
当你要自己控制Connection开关和事务的时候,可以通过DbUnifier(Connection con)这个构造函数来做
这点我完全明白,我谈论的重点是下面这部分
引用 89 楼 tigeryu 的回复:
另外,重点是交由DbUnifier控制,并不代表DbUnifier的关闭一定生效,因为有上层的容器会控制事务和连接创建和关闭,而我们使用往往是有Spring容器的,所以在一个线程里只会创建一个连接
1 你不可能硬性规定你的用户必须使用spring容器 2 如前面所述,重点不在于是不是同一个物理连接,而是因为这个close方法,有可能(根据你的配置和底层容器有区别)造成事务回滚等操作。换句话说,同一个连接但未必是一个事务(当然,也有可能是)。这样的设计可能造成以下几方面的问题: A 性能问题 B 事务不一致,“脏读”,“幻读”(与术语本意有些区别,但对于最终用户,感觉到的结果是一致的)等
引用 89 楼 tigeryu 的回复:
你如果不理解的话可以学习一下AOP和ThreadLocal的知识
我讨论的这部分貌似和AOP没有直接的关系。ThreadLocal的话,还是如上一部分“同一个连接但未必是一个事务” 最后总结下,不能说你这样的设定完全是错的。但是,针对我支出的问题,要么请赶快写出文档,要么,请在运行时做出限定。比如,使用非Connection构造函数时,检查当前运行环境,是否是受到了托管,否则异常。
wuyue-tiger 2014-06-03
  • 打赏
  • 举报
回复
全局Connection还是保留着的,还是有根据Connection创建DbUnifier的构造函数,只是现在Connection被置于了ConnectionDbSource这个对象里了。这样看上去代码从实现上看更一致,更易于理解。
wuyue-tiger 2014-06-03
  • 打赏
  • 举报
回复
引用 88 楼 shine333 的回复:
我还是想问:没事就喜欢关connection干嘛?难道,用你这个框架的人,任何事务里面最多只能有一个数据库操作?! 干嘛不是提供close/commit/rollback方法,让用户自己决定什么时候去提交,回滚,关闭? 还是回到getSequenceNextValue方法,麻烦你先把你的DbUtil.closeConnection方法里面,con.close();后面加上一行日志,同时,使用db-unifier.config.xml配置中的datasource(比如默认的DbUnifier)构造函数。 然后,再执行getSequenceNextValue,看看一共关闭了多少次? 我测试了下,如果是有多个线程(每个线程一个DbUnifier)同时操作,由于你做了多次UPDATE尝试,连接的开关次数会更多。调用一次getSequenceNextValue,平均每个线程竟然需要3次以上开关连接,而且随着测试线程数增加而增加。即使用了连接池,虽然物理连接没有关闭,但是由于调用了close,仍可能会涉及到自动回滚等事务型操作(依据缓冲池的种类及配置),在高并发下,你不停地getConnection/close设计,绝对是个噩梦。 还是那句话,你的整体设计,尤其是关于连接与事务要重新考量一下。 附带提一句,在mysql下,SYS_SEQ表不存在的话,你的getTable不是return null,而是抛错。
首先得说一句,这个工程还处于测试阶段,bug再所难免,您说的这个mysql下的bug确实存在,我已经更新了源代码,在下个版本会更新,感谢你的支持。 不过Connection这事,我得多说几句,首先db-unifier中允许用户自己控制Connection,也可以交由db-unifier控制,这个不矛盾。当你要自己控制Connection开关和事务的时候,可以通过DbUnifier(Connection con)这个构造函数来做,如果不想控制,则用其它构造函数。另外,重点是交由DbUnifier控制,并不代表DbUnifier的关闭一定生效,因为有上层的容器会控制事务和连接创建和关闭,而我们使用往往是有Spring容器的,所以在一个线程里只会创建一个连接,你如果不理解的话可以学习一下AOP和ThreadLocal的知识。
shine333 2014-06-03
  • 打赏
  • 举报
回复
我还是想问:没事就喜欢关connection干嘛?难道,用你这个框架的人,任何事务里面最多只能有一个数据库操作?! 干嘛不是提供close/commit/rollback方法,让用户自己决定什么时候去提交,回滚,关闭? 还是回到getSequenceNextValue方法,麻烦你先把你的DbUtil.closeConnection方法里面,con.close();后面加上一行日志,同时,使用db-unifier.config.xml配置中的datasource(比如默认的DbUnifier)构造函数。 然后,再执行getSequenceNextValue,看看一共关闭了多少次? 我测试了下,如果是有多个线程(每个线程一个DbUnifier)同时操作,由于你做了多次UPDATE尝试,连接的开关次数会更多。调用一次getSequenceNextValue,平均每个线程竟然需要3次以上开关连接,而且随着测试线程数增加而增加。即使用了连接池,虽然物理连接没有关闭,但是由于调用了close,仍可能会涉及到自动回滚等事务型操作(依据缓冲池的种类及配置),在高并发下,你不停地getConnection/close设计,绝对是个噩梦。 还是那句话,你的整体设计,尤其是关于连接与事务要重新考量一下。 附带提一句,在mysql下,SYS_SEQ表不存在的话,你的getTable不是return null,而是抛错。
wang_huanming 2014-06-03
  • 打赏
  • 举报
回复
不知道加入有什么能力要求吗,本人菜鸟一个,也想参加试试啊
shine333 2014-06-02
  • 打赏
  • 举报
回复
我不是来“找碴”的,但是来“找碴”的
引用 83 楼 tigeryu 的回复:
2、单元测试肯定是有的,在test下都是用JUnit写的测试用例。你发现的问题,正是db-unifier巧妙的地方。不象别的数据库工具,都是封闭的包装掉Connection,对外并不开放获取Connection的方法,在有些特殊场合会带来不方便。db-unifier允许从第三方传入Connection进行操作,灵活性得以体现。
} finally {
			if (this.con == null) {
				DbUtil.closeConnection(con);
			}
		}
引用 83 楼 tigeryu 的回复:
3、close方法都会抛SQLException,但是抛出后一般也是无法处理的,我们索性就不予处理这样的情况,捕获后直接转换成RuntimeException,无需再烦琐的写处理Exception的代码。另一个好处是在Spring的使用过程中,通过直接抛出RuntimeException可以直接对事务进行回滚,非常方便,无额外代码。
巧妙之处还改掉?,现在的代码还没看全,但是方向是对的,无论是放弃全局的connection,还是现在分层的finally。原来的做法,100%错误。
引用 83 楼 tigeryu 的回复:
我写了十几年的jdbc代码了,这个getObject我还是经常用的,但这个方法并不可靠的,一些对象并不能通过getObject获得,还有一些类型,不同数据库转出来的Object并不一致,这个对代码移植都是有害的,所以尽量避免使用这个方法。
我知道getObject在不同驱动下表现未必一致。不过,最常用的那些类型表现是一致的,所以建议你考虑对这部分使用。不过只是建议,你现在的写法本身(除了之前提的改成switch)没问题
引用 83 楼 tigeryu 的回复:
6、totalRowCount与size()的值含义并不相同啊,做过分页的人都知道totalRowCount指的是所有记录的总数,size()获得的只是当前页的记录数
OK,关于totalRowCount,size的区别,这里我看错了。不过,之前提到的,只读部分仍然有效。
引用 77 楼 shine333 的回复:
为什么RowSet的totalRowCount属性不是只读且自动与size或者说addRow方法绑定的。
也就是说,totalRowCount属性只读,只在addRow的时候+1
引用 83 楼 tigeryu 的回复:
请测一下getSequenceNextValue方法,此方法用表模拟序列是为了各数据库移植的问题,并且在算法中加入了乐观锁机制处理,完全可以保证多线程或者集群的情况下无重值,无跳号,准确无误。 另外提到的连接问题,如果是一般的使用方式,反复与数据库建立连接、关闭连接,性能一定比较差。但是一般我们都会用连接池,用ThreadLocal绑定事务,在这样的环境下,这完全不是个问题。
因为你完全改了DbUnifier的结构,这部分还没看。不过,当时我的意见,完全没错(基于全局con的版本:As of 5/28)
太上情 2014-05-31
  • 打赏
  • 举报
回复
虽然也想进去玩玩,但是我太菜了,小白一枚,正在java这条路上渐行渐远!
wonkju 2014-05-30
  • 打赏
  • 举报
回复
25,26 楼泼冷水的方式,坑爹呀... 本人也大三,虽然主要精力都花在java上,不过才学到 servlet,ssh框架还没有学. 不过对于开源项目很顶的,国内就应该有这精神...多多学习外国人的有些精神嘛...
wuyue-tiger 2014-05-30
  • 打赏
  • 举报
回复
引用 76 楼 shine333 的回复:
提下批评。 1 文档做的实在太差,其他不说DbUnifier.java里面竟然没一行javadoc 2 同样是DbUnifier,我很严肃的问你,你做过测试吗???尤其是覆盖度方面的测试? 检查一下所有
DbUtil.closeConnection(con);
前面的逻辑判断吧!!! 3 还是拿DbUnifier做例子,因为没有API说明,不是很清楚你的设计。但是里面竟然有那么多close connection操作?!另外就算你关闭,

		} finally {
			DbUtil.closeResultSet(rs);
			DbUtil.closeStatement(ps);
			if (this.con == null) {
				DbUtil.closeConnection(con);
			}
		}
closeResultSet/statement都是抛异常的,所以你的con还是可能没关闭——当然你的if,con是不可能关闭的 4 所有ColumnType相关的if, else if 链(包括判断ColumnType,还是DbUtil返回ColumnType的判断),统统改成switch,无论是效率上还是美观度上 5 小贴士。很多较新的JDBC驱动,直接ResultSet.getObject会自动根据列的类型,返回适合的Java类型。当然,我没有试过全部驱动。
有人吐嘈是好事啊,我们来一一探讨一下这位建议者指出的问题 1、文档差是差的,我的下一步工作就是完善文档。但对于JavaDoc我要说几句,个人认为好的代码不需要文档,从方法和变量的命名就能知晓功能用意,只有遇到非常复杂的算法时才需要加注释说明。 2、单元测试肯定是有的,在test下都是用JUnit写的测试用例。你发现的问题,正是db-unifier巧妙的地方。不象别的数据库工具,都是封闭的包装掉Connection,对外并不开放获取Connection的方法,在有些特殊场合会带来不方便。db-unifier允许从第三方传入Connection进行操作,灵活性得以体现。
} finally {
			if (this.con == null) {
				DbUtil.closeConnection(con);
			}
		}
这代码要仔细看,判断的是全局的con,是由第三方传入的,而不是方法内自己创建的con,这里实际上是判断是否第三方传入了con,如果传入的不用管它,否则就关闭自己创建的con,没有con无法关闭的问题。 3、close方法都会抛SQLException,但是抛出后一般也是无法处理的,我们索性就不予处理这样的情况,捕获后直接转换成RuntimeException,无需再烦琐的写处理Exception的代码。另一个好处是在Spring的使用过程中,通过直接抛出RuntimeException可以直接对事务进行回滚,非常方便,无额外代码。 4、这个纯属书写习惯问题,应该是不影响效率,可以考虑改一下 5、我写了十几年的jdbc代码了,这个getObject我还是经常用的,但这个方法并不可靠的,一些对象并不能通过getObject获得,还有一些类型,不同数据库转出来的Object并不一致,这个对代码移植都是有害的,所以尽量避免使用这个方法。
引用 77 楼 shine333 的回复:
6,一行很可爱的代码,暴露出API设计上的一个思路问题:
rowSet.setTotalRowCount(rowSet.size());
为什么RowSet的totalRowCount属性不是只读且自动与size或者说addRow方法绑定的。 也就是说
	public int getTotalRowCount() {
		return size();
	} // 并且去掉set方法
6、totalRowCount与size()的值含义并不相同啊,做过分页的人都知道totalRowCount指的是所有记录的总数,size()获得的只是当前页的记录数
引用 78 楼 shine333 的回复:
又看了几眼,你的DbUnifier类,也就是我很早以前说过 ,主要功能放在一个类里面肯定会出问题的。果然出问题了,你可以放弃现有设计,推到重来(只是指API的设计方面,具体的代码未必需要改动) 参考getSequenceNextValue方法。按照你每次close的操作,里面已经是好几个连接,好几个不同的事务了,话说,这样的SEQ能用吗?而且抛开这个不谈,你现在的所谓sequence设计,用的是一张表,然后一个列代表分类,一个列代表数值。话说,你都没有尝试同步操作(无论是Java的existsSequenceTable变量,还是对数据访问),不同线程/事务,同时读取的情况下,读到同一个值,那简直是家常便饭。而且,你的existsSequenceTable完全没用,如果人家应用程序是集群的话。 总之,还是重新设计一下吧。
请测一下getSequenceNextValue方法,此方法用表模拟序列是为了各数据库移植的问题,并且在算法中加入了乐观锁机制处理,完全可以保证多线程或者集群的情况下无重值,无跳号,准确无误。 另外提到的连接问题,如果是一般的使用方式,反复与数据库建立连接、关闭连接,性能一定比较差。但是一般我们都会用连接池,用ThreadLocal绑定事务,在这样的环境下,这完全不是个问题。
shine333 2014-05-29
  • 打赏
  • 举报
回复
又看了几眼,你的DbUnifier类,也就是我很早以前说过 ,主要功能放在一个类里面肯定会出问题的。果然出问题了,你可以放弃现有设计,推到重来(只是指API的设计方面,具体的代码未必需要改动) 参考getSequenceNextValue方法。按照你每次close的操作,里面已经是好几个连接,好几个不同的事务了,话说,这样的SEQ能用吗?而且抛开这个不谈,你现在的所谓sequence设计,用的是一张表,然后一个列代表分类,一个列代表数值。话说,你都没有尝试同步操作(无论是Java的existsSequenceTable变量,还是对数据访问),不同线程/事务,同时读取的情况下,读到同一个值,那简直是家常便饭。而且,你的existsSequenceTable完全没用,如果人家应用程序是集群的话。 总之,还是重新设计一下吧。
shine333 2014-05-29
  • 打赏
  • 举报
回复
6,一行很可爱的代码,暴露出API设计上的一个思路问题:
rowSet.setTotalRowCount(rowSet.size());
为什么RowSet的totalRowCount属性不是只读且自动与size或者说addRow方法绑定的。 也就是说
	public int getTotalRowCount() {
		return size();
	} // 并且去掉set方法
shine333 2014-05-29
  • 打赏
  • 举报
回复
提下批评。 1 文档做的实在太差,其他不说DbUnifier.java里面竟然没一行javadoc 2 同样是DbUnifier,我很严肃的问你,你做过测试吗???尤其是覆盖度方面的测试? 检查一下所有
DbUtil.closeConnection(con);
前面的逻辑判断吧!!! 3 还是拿DbUnifier做例子,因为没有API说明,不是很清楚你的设计。但是里面竟然有那么多close connection操作?!另外就算你关闭,

		} finally {
			DbUtil.closeResultSet(rs);
			DbUtil.closeStatement(ps);
			if (this.con == null) {
				DbUtil.closeConnection(con);
			}
		}
closeResultSet/statement都是抛异常的,所以你的con还是可能没关闭——当然你的if,con是不可能关闭的 4 所有ColumnType相关的if, else if 链(包括判断ColumnType,还是DbUtil返回ColumnType的判断),统统改成switch,无论是效率上还是美观度上 5 小贴士。很多较新的JDBC驱动,直接ResultSet.getObject会自动根据列的类型,返回适合的Java类型。当然,我没有试过全部驱动。
令狐-少侠 2014-05-29
  • 打赏
  • 举报
回复
引用 57 楼 u014480870 的回复:
[quote=引用 25 楼 sunbo624 的回复:] 没必要做这个 毫无用处
如果效果效益好,还是可以做。 虽然和一些框架重复了,但我们不能老用自行车,不去找机会发明摩托车吧。 社会在进步,我们不能止步不前。其实如果我们中国也搞几个更牛更实用的常用框架不是更好。 不能老用外国的,用我们中国人自己做的框架不是更好? 这个项目还要专业人士评估下可行和做出来的效果是否可以覆盖传统的框架等等(一些专业的问题),象我们这样的菜鸟,只是发表下个人见解。娱乐娱乐。 [/quote] 好!
令狐-少侠 2014-05-29
  • 打赏
  • 举报
回复
加入。和中国的开源事业一起成长。
张含韵 2014-05-29
  • 打赏
  • 举报
回复
强烈支持,暂时不会参与
朗晴 2014-05-28
  • 打赏
  • 举报
回复
支持支持。。。
wuyue-tiger 2014-05-28
  • 打赏
  • 举报
回复
继续在改进中,最近的更新主要有以下几点 varchar等类型中字符串超长的计算及处理 根据主从表关系的顺序导出数据库数据,保证导入时不会受外键限制 与Spring的集成方法,保证事务,并可与Hibernate等常见工具整合,一起使用
加载更多回复(70)

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧