Hibernate vs JPA vs JDO - 各自的优点和缺点?

时间:2009-02-09 22:03:09

标签: java hibernate orm jpa jdo

我熟悉ORM作为一个概念,几年前我甚至使用过nHibernate进行.NET项目;但是,我没有跟上Java中的ORM主题,也没有机会使用这些工具。

但是,现在我可能有机会开始为我们的某个应用程序使用一些ORM工具,试图摆脱一系列遗留Web服务。

我很难说出JPA规范之间的差异,你对Hibernate库本身的看法,以及JDO提供的内容。

所以,我明白这个问题有点开放,但我希望得到一些意见:

  • 各自的优点和缺点是什么?
  • 您对新项目有什么建议?
  • 在使用一个框架与另一个框架有意义的情况下是否存在某些条件?

11 个答案:

答案 0 :(得分:111)

一些注意事项:

  • JDO和JPA都是规范,而不是实现。
  • 如果您将代码限制为仅使用标准JPA,那么您可以交换JPA实现。 (同上JDO。)
  • Hibernate可以用作JPA的一个这样的实现。
  • 但是,Hibernate提供了一个原生API,其功能超越了JPA。

IMO,我会推荐Hibernate。


如果您需要使用特定于Hibernate的功能,那么您应该做些什么的评论/问题。有很多方法可以看看这个,但我的建议是:

  • 如果您对供应商搭配的前景并不担心,那么请在Hibernate和其他JPA和JDO实现之间做出选择包括决策中各种供应商特定的扩展

  • 如果您对供应商搭配的前景感到担心,并且您不能在不诉诸供应商特定扩展的情况下使用JPA,那么请不要使用JPA。 (同上JDO)。

实际上,您可能需要权衡与供应商合作相关的多少需要这些供应商特定扩展的多少

还有其他因素,例如您/您的员工对各自技术的了解程度,产品在许可方面的成本,以及您对JDO和JPA未来将会发生什么的故事。

答案 1 :(得分:68)

确保评估JDO的DataNucleus实现。我们从Hibernate开始,因为它看起来很受欢迎,但很快就意识到它不是100%透明的持久性解决方案。有太多的警告,文档中充满了'如果你遇到这种情况,那么你必须编写这样的代码',这会带走我们想要的自由建模和编码的乐趣。 JDO 从未让我调整我的代码或我的模型以使其“正常工作”。我可以设计和编写简单的POJO,就好像我只在内存中使用它们一样,但我可以透明地保留它们。

JDO / DataNucleus相对于hibernate的另一个优点是它没有所有的运行时反射开销,而且内存效率更高,因为它使用构建时字节码增强(可能会为你的构建时间增加1秒)而不是hibernate的运行时反射驱动的代理模式。

你可能会觉得Hibernate令人烦恼的另一件事是你对你认为对象的引用...它通常是对象的“代理”。如果没有字节码增强的好处,则需要代理模式以允许按需加载(即,当您拉入顶级对象时避免拉入整个对象图)。准备重写equals和hashcode,因为您认为引用的对象通常只是该对象的代理。

以下是使用Hibernate获得的令人沮丧的一个例子,您将无法使用JDO:

http://blog.andrewbeacock.com/2008/08/how-to-implement-hibernate-safe-equals.html
http://burtbeckwith.com/blog/?p=53

如果你喜欢编码'workarounds'那么,当然,Hibernate适合你。如果您喜欢干净,纯粹,面向对象,模型驱动的开发,您将所有时间都花在建模,设计和编码上,而不是在丑陋的变通方法上花费几个小时来评估JDO/DataNucleus。投入的时间将被偿还一千倍。

2017年2月更新

很长一段时间以来,除了JDO持久性标准之外,DataNucleus还实现了JPA持久性标准,因此将现有的JPA项目从Hibernate移植到DataNucleus应该非常简单,你可以非常直接地获得DataNucleus的所有上述优点。代码变化很小,如果有的话。 所以就问题而言,选择一个特定的标准,JPA(仅限RDBMS)与JDO(RDBMS + No SQL + ODBMSes +其他),DataNucleus同时支持,Hibernate仅限于JPA。

Hibernate DB更新的性能

选择ORM时要考虑的另一个问题是其脏检查机制的效率 - 当需要构造SQL来更新当前事务中已更改的对象时,这变得非常重要 - 特别是当有很多对象。 在这个SO答案中有一个关于Hibernate脏检查机制的详细技术说明: JPA with HIBERNATE insert very slow

答案 2 :(得分:51)

我最近评估并选择了一个java项目的持久性框架,我的发现如下:

我所看到的是支持 JDO 的支持主要是:

  • 你可以使用非sql数据源,db4o,hbase,ldap,bigtable,couchdb(cassandra的插件)等。
  • 您可以轻松地从sql切换到非sql数据源,反之亦然。
  • 没有代理对象,因此对hashcode()和equals()实现的痛苦减少了
  • 更多POJO因此需要更少的解决方法
  • 支持更多关系和字段类型

支持 JPA 的支持主要是:

  • 更受欢迎
  • jdo已经死了
  • 不使用字节码增强

我看到很多来自JPA开发人员的亲JPA帖子明显没有使用JDO / Datanucleus提供不使用JDO的弱论据。

我也看到很多来自JDO用户的帖子已经迁移到JDO并且结果更加快乐。

就JPA更受欢迎而言,这似乎部分是由于RDBMS供应商的支持,而不是技术上的优势。 (对我来说听起来像VHS / Betamax)。

JDO和它的参考实现Datanucleus显然没有死,正如Google为GAE采用它并在源代码上积极开发所示(http://sourceforge.net/projects/datanucleus/)。

由于字节码增强,我看到了一些关于JDO的抱怨,但还没有解释为什么它是坏的。

事实上,在NoSQL解决方案越来越痴迷的世界中,JDO(以及数据核实现)似乎是一个更安全的选择。

我刚刚开始使用JDO / Datanucleus并设置它,以便我可以在使用db4o和mysql之间轻松切换。使用db4o快速开发很有帮助,不必过多担心数据库模式,然后一旦模式稳定部署到数据库。我也相信,以后我可以将我的全部/部分应用程序部署到GAE,或者利用分布式存储/映射 - 减少la hbase / hadoop / cassandra而不需要太多重构。

我发现开始使用Datanucleus的最初障碍有点棘手 - 关于datanucleus网站的文档有点难以理解 - 这些教程并不像我希望的那样容易理解。话虽如此,一旦你超越初始学习曲线,关于API和映射的更详细的文档就非常好。

答案是,这取决于你想要什么。我宁愿拥有更清晰的代码,没有供应商锁定,更多以pojo为导向,nosql选项更受欢迎。

如果你想要温暖的挑剔感觉你和大多数其他开发者/绵羊一样,那就选择JPA / hibernate。如果你想在你的领域领先,试驾JDO / Datanucleus并自己动手。

答案 3 :(得分:39)

  

您建议哪个新项目?

我建议不要!将Spring DAO的JdbcTemplateStoredProcedureRowMapperRowCallbackHandler一起使用。

我自己在Hibernate方面的个人经验是,预先节省的时间远远超过你将花费大量时间来尝试理解和调试意外的级联更新行为等问题。

如果您使用的是关系数据库,那么代码越接近它,您拥有的控制就越多。 Spring的DAO层允许精确控制映射层,同时不需要样板代码。此外,它集成到Spring的事务层中,这意味着您可以非常轻松地添加(通过AOP)复杂的事务行为,而不会侵入您的代码(当然,您也可以使用Hibernate)。

答案 4 :(得分:23)

  

JDO已经死了

JDO实际上并没有死,所以请检查一下你的事实。 JDO 2.2于2008年10月发布 JDO 2.3正在开发中。

这是在Apache下公开开发的。比JPA更多的版本,其ORM规范仍然比JPA2提出的功能提前了

答案 5 :(得分:15)

JDO具有高于JPA的高级功能,请参阅http://db.apache.org/jdo/jdo_v_jpa.html

答案 6 :(得分:10)

我正在使用JPA(来自Apache的OpenJPA实现,该实现基于KODO JDO代码库,该代码库已有5年以上且极其快速/可靠)。恕我直言,任何告诉你绕过规格的人都会给你不好的建议。我把时间放进去,肯定得到了回报。使用JDO或JPA,您可以通过最小的更改来更改供应商(JPA具有orm映射,因此我们谈论的可能不到一天,可能会更改供应商)。如果你有像我这样的100多个表,这是巨大的。另外,你可以通过集群式缓存驱逐来构建内置缓存,这一切都很好。 SQL / Jdbc适用于高性能查询,但透明持久性远优于编写算法和数据输入例程。我的整个系统中只有大约16个SQL查询(50k +代码行)。

答案 7 :(得分:9)

任何说JDO已经死亡的人都是一个天体冲浪的FUD贩子并且他们知道。

JDO活得很好。与更年轻和受限制的JPA相比,该规范仍然更加强大,成熟和先进。

如果您希望仅限于JPA标准中的可用内容,您可以编写JPA并使用DataNucleus作为高性能,更透明的持久性实现,而不是JPA的其他实现。当然,如果您想要JDO带来的建模的灵活性和效率,DataNucleus也会实现JDO标准。

答案 8 :(得分:8)

我自己一直在研究这个问题,但两者之间并没有找到很大的区别。我认为最重要的选择是你使用哪种实现方式。对于我自己,我一直在考虑DataNucleus平台,因为它是两者的数据存储无关的实现。

答案 9 :(得分:2)

我在同一个项目中使用了Hibernate(JPA实现)和JPOX(JDO实现)。 JPOX工作正常,但很快就遇到了bug,那里有一些当时不支持的Java 5语言功能。它在使用XA事务时遇到了问题。我正在从JDO对象生成数据库模式。它希望每次都连接到一个数据库,如果你的Oracle连接不能正常工作,那就很烦人了。

然后我们切换到Hibernate。我们玩了一段时间只使用纯JPA,但我们需要使用一些Hibernate特定的功能来进行映射。在多个数据库上运行相同的代码非常容易。 Hibernate似乎积极地缓存对象或者有时只是有奇怪的缓存行为。 Hibernate无法处理一些DDL构造,因此它们在运行以初始化数据库的附加文件中定义。当我遇到Hibernate问题时,通常会有很多人遇到同样的问题,这使得谷歌搜索解决方案变得更容易。最后,Hibernate似乎设计得很好,也很可靠。

其他一些响应者建议只使用SQL。对象关系映射的真正杀手用例是测试和开发。为处理大量数据而构建的数据库通常很昂贵,或者很难安装。他们很难测试。有许多内存中的Java数据库可用于测试,但通常对生产无用。能够使用真实但有限的数据库将提高开发效率和代码可靠性。

答案 10 :(得分:1)

我在2012年5月制作了一个使用JDO 3.0& DataNucleus 3.0 - 看看它有多干净: https://github.com/TorbenVesterager/BadAssWebApp

好吧也许它有点太干净,因为我将POJO用于​​数据库和JSON客户端,但它很有趣:)

PS:包含一些SuppressWarnings注释(在IntelliJ 11中开发)