在Java世界,Hibernate是最引人关注的一个话题。从Gavin King加入EJB3.0 EG,负责制订EJB3.0的持久层规范;到Gavin King非正式退出JDO EG,并且充满个人情绪的攻击JDO2.0规范;到《Hibernate in Action》的发行;再到Hibernate3 Alpha的发布;最后再到最近JBoss 3.0 PR的发布(使用Hibernate3实现Entity Bean)。可以说这其中的每一步都引起业界的侧目。
Hibernate在不到3年的时间里,从一个不起眼的开源软件发展到今天令业界瞩目的主流O/R Mapping框架,Gavin King从一个开源软件的作者成为业界举足轻重的人物,这多少有些传奇的色彩。毕竟,单纯从技术成就而言,Hibernate不算是最有成就的Java开源框架软件,到目前为止也不是一个完美无缺的软件;从个人技术水平而言,Gavin King也不算绝顶高手。
在当前的Java持久层框架中,最流行的O/R Mapping产品分别是Hibernate,JDO和TopLink。
自从去年Gavin King加入JBoss之后,Hibernate已经由一个民间的开源软件走上了兼容EJB EntityBean的道路。然而更加令人侧目的是,Gavin King在EJB3.0 EG中充当了一个非常重要的角色,只要对比一下EJB3.0的EntityBean和Hibernate3,真相就会大白,虽然API接口不同,但是 EntityBean的设计理念完全来自于Hibernate。
虽然EJB3.0的EntityBean在相当程度上来源于Hibernate,但是毕竟是不同的API接口,因此Hibernate和EJB3.0 EntityBean究竟是怎样的一种关系,是很多人心中的疑问。
2004年四月份JBoss的Ben Wang访华期间,我曾经向Ben请教Hibernate的未来发展,他回答说,Hibernate未来将仍旧以独立的软件产品存在和发展,既可以 outside EJB container使用;同时Hibernate也将做为JBoss EntityBean Implementation,又可以inside EJB container使用。然而如何既inside,又outside,终究缺乏一个感性的认识。
10月8日JBoss发布的EJB3.0 PR揭开了答案。从Sourceforge的CVS服务器上面checkout出来源代码看一下,我们可以发现,Gavin King对Hibernate3进行了简单的封装,将EJB 3.0 EntityBean API调用转换为内部Hibernate3自己的API,从而实现EJB3.0 EntityBean的兼容。
EJB3.0不承诺脱离容器调用,如果你想享用EJB3.0,则必须运行在某个EJB Vendor提供的容器内,例如你使用JBoss提供的容器,那么你调用的是EntityBean API,这些调用请求会被转换为Hibernate API的调用请求。这意味着Hibernate实际上提供了两套API:一套是Hibernate原生API;另一套是兼容EJB3.0 EntityBean API。对于那些需要分布式调用支持,需要EJB容器的开发人员来说,他们选择后一套API;对于不需要EJB容器的开发人员来说,他们选择前一套 API。这就是Hibernate既定的发展策略。
今年夏天投票通过的JDO2.0标准从某种程度而言,并不逊色于Hibernate当前的版本,有些功能甚至比Hibernate还要好,例如 JDO支持对类属性的lazy loading,而Hibernate要到3才支持,当前Hibernate仅仅支持类的lazy loading。实际上在去年,就已经有很多用户不断提出对类属性的lazy loading的需求,然而Gavin King当时一直不认为这个需求有添加的必要性。再例如被Gavin King形容为“可憎的”JDOQL,实际上是类SQL查询语言和对象条件查询的混合体。从功能上来说,不如HQL强大,但是比Hibernate自己的条件查询强。
不知道究竟出于什么原因,Gavin King对JDO似乎一直怀有由衷的厌恶,5月,他在Hibernate的blog上面对JDO进行了毫不留情的批判,列举了JDO的种种缺点来解释为什么EJB3持久层规范没有把JDO考虑进去。然而事实上他的批判充满了对JDO的误解和偏见,例如Gavin King憎恨JDOQL丝毫没有什么特别的理由,只因为JDOQL不是一个纯粹的查询语言,而是一个混合体,这多少让人对Gavin King的风度感到遗憾。在被SolarMetric的Abe White反驳之后,同样没有风度的说,“我可没有时间做这种无谓的争论,事实上每个人都认为他自己的技术是最好的……我是错了,JDO那伙人也错了,每个人都会犯错误……”。(所以说人无完人阿!)
JDO2规范的出台事实上构成了对Hibernate,乃至基于Hibernate理念的EJB3.0 EntityBean的严重威胁。JDO1.0规范在功能上的严重缺失导致了JDO无力面对Hibernate和TopLink的竞争,然而功能基本完备的JDO2挟众多JDO Vendor商业支持的合力,同时JDO规范可以避免产品锁定在某个Vendor的优势,已经将竞争的天平拉直。
然而JDO2和EJB3两大商业主流标准的分裂,是大部分人,甚至包括厂商所不希望看到的。 于是最终EJB3的Lead Linda DeMichiel和JDO2的Lead Craig Russell联名发表公开信,宣布了一个合并EJB3和JDO2持久层规范的计划,新的持久层规范将以JSR-220(EJB3.0)的持久层规范为基础,融合JDO2的部分特性。新的持久层规范将进入J2EE1.5之中,独立于EJB存在,既可以inside J2EE容器来使用,也可以脱离J2EE容器,独立的运行。
这个新的持久层框架可以说完全是一个政治的产物。EJB Vendors出于自身利益反对JDO,使得JDO没有办法成为J2EE的一部分,然而标准的分裂也是大部分人更加不希望看到的,于是最终JDO成了政治斗争的牺牲品。从表面上来看,JDO和EJB3.0 EntityBean都将被新的持久层框架取代,似乎JDO并没有吃亏,但实际上JDO2标准已经成熟,部分JDO领导厂商的产品已经蓄始待发,而 EJB3.0 EntityBean还处于Early Draft,等待产品诞生至少也是一年之后的事情了;另外值得耐人寻味的是,新的持久层框架将基于当前EJB3.0 EntityBean,再结合JDO2的规范,并且将处于EJB3.0 EG的控制之下,再加入一些JDO2 EG的成员。因此可以看出来新的持久层框架无疑还是以EJB3.0 EG为主导进行制定的。
从长远来看,EJB3和JDO2的政治斗争对双方都有好处,长期分裂带来的后果对双方的发展都不利,然而从短期来看,JDO2确实是在这场政治斗争中败下阵来。最直接的体现就是,已经有一些JDO的用户对JDO的前景产生了动摇和迷茫,不少的JDO爱好者更是直言JDO将死。
TopLink是一个老牌的O/R Mapping软件了,自从被Oracle收购之后,又增加了对Oracle数据库的良好支持,和对Oracle AS EntityBean的支持。Oracle提供了TopLink的图形设计环境,可以使得设计好的TopLink域模型既可以被单独用在TopLink 中,也可以被用在EJB CMP中。因此看来TopLink也走了一条和Hibernate同样策略的路。
TopLink的问题在于相比Hibernate的开源和免费的优势来说,TopLink既不开源,售价又不菲上。本来商业软件TopLink应该在技术支持和商业宣传策略上拥有足够的优势,然而Oracle公司毕竟是一个以数据库为核心产品的公司,其他的一切产品都是为了数据库销售业绩而服务的。在Oracle产品线中处于一个从属地位的TopLink,由于先天不足,只能眼睁睁看着Hibernate的日益壮大而无所作为,因此 TopLink更多的被局限在购买了Oracle数据库,并且绑定Oracle数据库的用户群体中。
J2EE1.5的新持久层规范将毫无悬念的成为未来持久层框架的主流API,无论是Hibernate,JDO,还是TopLink终将兼容这个主流商业API。在当前的这三种持久层API当中,Hibernate无疑是最有前途的。这是因为:
1、新的持久层规范将基于EJB3.0 EntityBean规范,这意味着仍将以Hibernate的设计理念为基础
2、JBoss对EJB3.0规范跟随的步伐非常紧密,在规范制定过程中就不断的发布参考实现产品,因此可以对对EJB3.0规范产生比较大的影响力。
综上所述,我们有理由对Hibernate的前途抱有强烈的信心。
最后的一个疑问是,既然J2EE1.5的新持久层框架可以脱离J2EE容器运行,那么大家不全部都去用Hibernate的后一套兼容API,而完全放弃Hibernate的原生API了吗?那么是否意味着Hibernate做为一个独立产品的使命彻底终结呢?
对于这个问题我的看法是:J2EE1.5的持久层规范要综合各个EJB Vendor,JDO Vendor的意见,要平衡他们之间的利益得失,那么这样一个瞻前顾后的规范必然无法覆盖所有应用场合的全面需要,这不像Hibernate的原生API 可以随时根据开发人员的要求增加功能那么灵活。因此我预计Hibernate的原生API以其更加强大的功能仍然会吸引一大批人直接使用原生API,而不是兼容J2EE规范的API。
总而言之,对于我们当前的持久层开发来说,最好的办法莫过于坚定的使用DAO层来隔离持久层和业务层逻辑,那么不管未来持久层风云如何变换,但凡基于POJO的持久层框架都可以被我们拿来任意替换。