从事研发管理奔八了,今天有点闲情,记录一下javaorm经过的日子;
刚工作时,写过简单网站,后来做过稍大的Web系统,整过ERP,当然都是Java方向的;
ORM(Object/Relation Mapping)(对象关系映射),相信现在大家已经非常熟悉,并且已经深刻理解;记得刚毕业那会,Hibernate就已经非常火爆,当时跟他类似的框架也很多,如企业级的toplink(已经被oracle捐献给eclipse社区了),大家说半ORM的ibatis等,当时还有apache的commons-dbutils(对JDBC的一个简单封装);
toplink:虽然是企业级,代码质量也有保证,稳定性也有保证,但是因为没有hibernate开放,所以当时一般是跟Oracle厂家的产品有关系的开发使用这个最好;
ibatis:它的特点就是纯sql语句,网上有专门的测试数据,说它比hibernate执行快,最接近jdbc;后来更名为mybatis;
(其实不管是什么数据库操作框架,查询数据操作,到最后都是从数据库中取ResultSet进行读取)
commons-dbutils:简单,好用,入门快,看官网几个eg就行,只需要程序员会sql;
另外一些大型的ERP公司或专业做产品公司,都有公司自己一套ORM,不管是从开源拿来改,还是完全自己开发,都有;
还有Sun又引入了JPA ORM规范,出于两个原因:其一,简化现有Java EE和Java SE应用开发工作;其二,Sun希望整合ORM技术,实现天下归一;
(野心很大!)
使用:
hibernate,我最开始觉得并没有为我开发效率提高多少,当时觉得很麻烦,开发网站时用的是dbutils或ibatis,或者直接jdbc,其实这个时候对hibernate的定位错了,之后做大点的Web系统时,hibernate确实省了不少时间,特别是我们开发了一个hibernate相关自动化生成工具后,效率倍增;当时这个工具是使用dbutils、swing开发出来的,不过后来弃用了,因为网上出来了更好的工具;
ibatis,刚工作的时候,一个朋友做电信的项目,他们公司技术总监选数据库框架选的就是ibatis,记得当时他跟我说公司技术总监说这个速度快,当时hibernate效率瓶颈好像爆料不少(现在改变很大,特别是hibernate的缓存技术使效率提高不少);
我用过ibatis和jsf开发过一个系统,感觉查询很方便,特别是复杂的SQL查询;没有做过压力测试,效率方面不好发表意见;
toplink,这个框架没使用过,只是得知,是一个企业级的框架,并且有大公司oracle支持;
dbutils,其实这个不算一个ORM框架,但是个人使用的感觉很不错,写过不少代码自动化生成工具,及一些小工具,都是使用的dbutils;
而且oschina也使用的dbutils;这里有相关代码:http://www.oschina.net/code/search?q=dbutils
我所了解的几个ERP厂商的ORM使用的是自身开发的ORM,因为一般大型ERP系统都是部署在大型EJB中间件中,远程调用使用EJB调用,因为ERP系统最重要的是数据信息和数据安全,像这种企业组件,中间件会赋予很多特性,而且中间件本身也提供很多特性;
jpa,现在jpa已经很成熟稳定了,大家也都用了很长时间,我做的几个系统也用到了jpa,还不错,而且事务管理也很方便,移植更改实现也挺方便,因为有不少变态的客户,对你做系统的技术,他要参与并且知晓并指定;
不是说jpa没有缺点,反而缺点很明显,除了官方缺点,项目开发应用时缺点也很明显,记得之前一个项目,一个开发人员拿着一个纯属SQL找过来要讨论,问JPA里怎么查,好像只能返回Entity或List<Object[]>,自定义非Entity对象或其它集合对象均不行;
其实之前项目已经碰到过,不过都是返回List<Object[]>后再进行处理,一般不超过一二十个这样的查询,所以之前也就让开发直接那样处理,但是现在这个项目报表及复杂数据展现比较多,这种查询少说也有四五十个以上,考虑增加了一次中间转换影响效率不少,所以决定修改jpa实现;
分析hibernate jpa实现:
hibernate的EntityManager实现为:org.hibernate.ejb.AbstractEntityManagerImpl;536行createNativeQuery方法; 由这个入口,进行分析hibernate的jpa实现;
过程略一万字............
hibernate中处理加载数据集的是org.hibernate.loader.custom.CustomLoader,在其243行有如下代码:
this.rowProcessor = new ResultRowProcessor(
hasScalars,
( ResultColumnProcessor[] ) resultColumnProcessors.toArray( new ResultColumnProcessor[ resultColumnProcessors.size() ] )
这里就是一个类似ResultSetHandler的实现类,但是是按行处理,所以我们改造时,为了使改动最小化,也按行处理即可;
其中 Query createNativeQuery(String sqlString, Class resultClass) 中的Class最后存在这个参数中:
那么现在我们看看,它是怎么传进这里的:
如下图,这是hibernate创建纯SQL查询的方法,最下面的一个方法就是新加的,准备使用ResultSet处理接口:
注意的是,要按第一个红框中的代码进行改造,加参数;
如下图:
然后在Query,NativeSQLQueryPlan,NativeSQLQuerySpecification,SQLQueryImpl,CustomQuery,SQLCustomQuery接口及类中增加RowResultSetProcessor传递的方法及属性;
最后改造一个CustomLoader构造方法最下面的代码即可,如下:
if (customQuery.getRowResultSetProcessor() == null) {
this.rowProcessor = new ResultRowProcessor(hasScalars,
(ResultColumnProcessor[]) resultColumnProcessors.toArray(new ResultColumnProcessor[resultColumnProcessors
.size()]));
} else {
this.rowProcessor = customQuery.getRowResultSetProcessor();
this.rowProcessor.setHasScalars(hasScalars);
this.rowProcessor.setColumnProcessors((ResultColumnProcessor[]) resultColumnProcessors
.toArray(new ResultColumnProcessor[resultColumnProcessors.size()]));
}
改造完后,编译覆盖即可;
当前hibernate版使用的是3.6版;