hibernate与JPA与JDO – 每个的利弊?
我熟悉ORM作为一个概念,几年前我甚至使用nHibernate来开发一个.NET项目。 但是,我没有跟上Java的ORM主题,并没有机会使用任何这些工具。
但是,现在我可能有机会开始为我们的应用程序使用一些ORM工具,试图摆脱一系列传统的Web服务。
我很难说出JPA规范,Hibernate库本身和JDO提供的内容之间的区别。
所以,我明白这个问题有点开放,但是我希望能得到一些意见:
- 各有什么优点和缺点?
- 你会build议一个新的项目?
- 是否有一定的条件,使用一个框架与另一个框架是有意义的?
一些说明:
- JDO和JPA都是规范,而不是实现。
- 这个想法是你可以交换JPA实现,如果你限制你的代码只使用标准的JPA。 (JDO同上)
- Hibernate可以被用作JPA的一个这样的实现。
- 但是,Hibernate提供了一个本地API,其function超出了JPA的function。
国际海事组织,我会推荐hibernate。
如果您需要使用特定于Hibernate的function,您应该做些什么意见/问题。 有很多方法来看待这个,但我的build议是:
-
如果您不担心与供应商绑定的前景,那么您可以在Hibernate和其他JPA和JDO实现( 包括各种供应商特定的扩展)之间进行select。
-
如果您担心供应商绑定的前景,并且您不能使用JPA而不诉诸供应商特定的扩展,则不要使用JPA。 (同上JDO)。
实际上,您可能需要权衡供应商搭配所担心的多less , 以及您需要这些供应商特定扩展的多less 。
还有其他一些因素,比如你/你的员工对于各自技术的了解程度,产品的授权费用,以及你相信JDO和JPA将来会发生什么事情的故事。
确保你评估JDO的DataNucleus实现。 我们从Hibernate开始,因为它似乎非常stream行,但很快就意识到它不是一个100%透明的持久性解决scheme。 有太多的注意事项,文档充满了“如果你有这种情况,那么你必须写这样的代码”,这就消除了我们想要的自由build模和编码的乐趣。 JDO 从来没有让我调整我的代码或模型,使其“正常工作”。 我可以简单地devise和编写简单的POJO,就好像我只是在内存中使用它们一样,但是我可以透明地坚持它们。
JDO / DataNucleus比hibernate的另一个优点是它没有全部的运行时间reflection开销,并且因为它使用了构build时间字节码增强(可能为你的大型项目增加1秒的构build时间)比hibernate的运行时reflection动力代理模式。
另一件你可能会觉得讨厌Hibernate的事情是,你必须引用你认为的对象……它通常是对象的“代理”。 没有字节码增强的好处,代理模式需要允许按需加载(例如,当您拉入顶层对象时避免拉入整个对象图)。 准备重写equals和hashcode,因为你认为你引用的对象通常只是该对象的代理。
这里有一个使用Hibernate的例子,你不会用JDO得到:
http://blog.andrewbeacock.com/2008/08/how-to-implement-hibernate-safe-equals.html
http://burtbeckwith.com/blog/?p=53
如果你喜欢编码“解决方法”,那么,当然,Hibernate是给你的。 如果您喜欢纯粹的,面向对象的,模型驱动的开发,那么您将所有的时间都花在build模,devise和编码上,而没有用于丑陋的解决方法,那么就花几个小时来评估JDO / DataNucleus 。 投入的时间将被偿还千倍。
2017年2月更新
相当长一段时间以来,DataNucleus'除了JDO持久性标准之外,还实现了JPA持久性标准,因此将现有的JPA项目从Hibernate移植到DataNucleus应该是非常简单的,只需很less的代码改变即可获得DataNucleus的所有上述好处,如果有的话。 所以就这个问题来说,select一个特定的标准,JPA(只有RDBMS)和JDO(RDBMS +没有SQL + ODBMSes +其他),DataNucleus同时支持,Hibernate仅限于JPA。
Hibernate数据库更新的性能
在selectORM时需要考虑的另一个问题是其脏检查机制的效率 – 当需要构buildSQL来更新当前事务中已更改的对象时(特别是在存在大量对象时),这一点变得非常重要。 在这个答案中有一个Hibernate的脏检查机制的详细技术描述: 与HIBERNATE插入JPA非常缓慢
我最近评估并select了一个Java项目的持久性框架,我的发现如下:
我所看到的是支持JDO的主要是:
- 你可以使用非sql数据源,db4o,hbase,ldap,bigtable,couchdb(cassandra的插件)等
- 您可以轻松地从一个SQL切换到非SQL数据源,反之亦然。
- 没有代理对象,因此对hashcode()和equals()实现的痛苦较less
- 更多的POJO,因此需要更less的解决方法
- 支持更多的关系和字段types
而支持JPA的支持主要是:
- 更stream行
- jdo死了
- 不使用字节码增强
我看到很多来自JPA开发者的亲JPA职位,他们明显没有使用JDO / Datanucleus提供的不使用JDO的弱点。
我也看到很多来自JDO用户的post,他们已经迁移到JDO,因此更加快乐。
关于JPA越来越受欢迎,似乎这是由于RDBMS供应商的支持,而不是技术上的优越。 (听起来像VHS / Betamax对我来说)。
JDO和它的参考实现Datanucleus显然不是死的,正如谷歌将其用于GAE以及在源代码(http://sourceforge.net/projects/datanucleus/)上的积极开发所展示的。;
由于字节码的增强,我看到了一些关于JDO的抱怨,但没有解释为什么它不好。
实际上,在一个越来越被NoSQL解决scheme所迷惑的世界里,JDO(和数据核实现)似乎是一个更安全的select。
我刚刚开始使用JDO / Datanucleus,并设置了它,以便在使用db4o和mysql之间轻松切换。 使用db4o进行快速开发会很有帮助,而不必过多地关心数据库模式,然后在架构稳定后部署到数据库。 后来我也确信,我可以将全部/部分应用程序部署到GAE,或者利用分布式存储/映射 – 减lessla hbase / hadoop / cassandra,而不需要太多的重构。
我发现Datanucleus开始有点棘手的第一个障碍 – datanucleus网站上的文档是有点难以进入 – 教程不像我希望的那样容易遵循。 话虽如此,一旦你通过最初的学习曲线,关于API和映射的更详细的文档是非常好的。
答案是,这取决于你想要的。 我宁愿有更清晰的代码,没有供应商locking,更多pojo为导向,更stream行的nosql选项。
如果你想要像大多数其他开发人员/羊一样热烈的挑剔的感觉,selectJPA /hibernate。 如果你想在你的领域领先,试试JDO / Datanucleus,并让自己的头脑。
你会build议一个新的项目?
我也不会build议! 改用Spring DAO的JdbcTemplate
和StoredProcedure
, RowMapper
和RowCallbackHandler
。
我个人对于Hibernate的经验是,预先保存的时间已经被无尽的日子所弥补,你将花费在线上来试图理解和debugging意外的级联更新行为等问题。
如果你使用的是关系数据库,那么你的代码越接近它,你拥有的控制就越多。 Spring的DAO层允许精确控制映射层,同时消除对样板代码的需求。 此外,它集成到Spring的事务层,这意味着你可以非常容易地添加(通过AOP)复杂的事务行为,而不会侵入你的代码(当然,你也可以用Hibernate来获得这个)。
JDO已经死了
JDO实际上并没有死,所以请检查你的事实。 JDO 2.2于2008年10月发布JDO 2.3正在开发中。
这是在Apache下公开开发的。 JPA比JPA有更多的发行版本,其ORM规范甚至比JPA2提出的特性还要早
JDO具有高于JPA的高级function,请参阅http://db.apache.org/jdo/jdo_v_jpa.html
我正在使用JPA(Apache的OpenJPA实现,基于KODO JDO代码库,这个代码基于5年以上,非常快速/可靠)。 恕我直言,任何人告诉你绕过规格给你不好的build议。 我把时间放在,并肯定得到回报。 无论使用JDO还是JPA,只需进行最less的更改就可以更改供应商(JPA有orm映射,所以我们不到一天的时间就可能改变供应商)。 如果你有100多个像我这样的表是巨大的。 另外,您可以使用集群式caching驱逐和caching技术来构buildcaching。 对于高性能查询,SQL / Jdbc是很好的,但透明持久性对于编写algorithm和数据input例程来说是远远优越的。 我在整个系统中只有大约16个SQL查询(50k行代码)。
任何一个说JDO已经死了的人,都是一个天生的FUD商人,他们知道这一点。
JDO还活着。 这个规范比起更年轻,更有约束的JPA更强大,更成熟和先进。
如果只想限制JPA标准中的可用内容,则可以写入JPA,并使用DataNucleus作为比JPA的其他实现更高性能,更透明的持久性实现。 当然,如果您想要JDO带来的build模的灵活性和效率,DataNucleus也会实现JDO标准。
我一直在研究这个,不能在两者之间find很大的区别。 我认为最重要的select是在哪个实施中使用。 对于我自己,我一直在考虑DataNucleus平台,因为它是两个数据存储不可知的实现。
我在同一个项目中使用了Hibernate(JPA实现)和JPOX(JDO实现)。 JPOX工作正常,但很快就遇到了错误,那里有一些当时不支持的Java 5语言function。 在XA交易中玩的很好。 我正在从JDO对象生成数据库模式。 它想每次连接到一个数据库,如果你的Oracle连接发生故障,这是令人讨厌的。
然后,我们切换到hibernate。 我们玩弄了一段时间只使用纯粹的JPA,但我们需要使用一些Hibernate的特定function来做映射。 在多个数据库上运行相同的代码非常简单。 Hibernate似乎积极地caching对象,或者有时候会有奇怪的caching行为。 有一些Hibernate无法处理的DDL结构,所以它们被定义在一个运行的初始化数据库的附加文件中。 当我碰到一个Hibernate的问题时,经常有许多人遇到同样的问题,这使得解决scheme的search更容易。 最后,Hibernate似乎devise良好,可靠。
其他一些响应者build议只使用SQL。 对象关系映射的真正杀手级用例是testing和开发。 构build用于处理大量数据的数据库通常很昂贵,或者难以安装。 他们很难testing。 有很多内存中的Java数据库可以用来testing,但通常对于生产无用。 能够使用真实而有限的数据库将提高开发生产力和代码可靠性。
我在2012年5月使用JDO 3.0和DataNucleus 3.0做了一个示例WebApp – 看看它是多么的干净: https : //github.com/TorbenVesterager/BadAssWebApp
好,也许这有点太干净,因为我使用POJO数据库和JSON客户端,但它很有趣:)
PS:包含一些SuppressWarnings注释(在IntelliJ 11中开发)