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

我很熟悉 ORM 这个概念,几年前我甚至用 nHibernate 作为。然而,我还没有跟上 Java 中 ORM 的主题,也没有机会使用这些工具中的任何一个。

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

我很难区分 JPA 规范、 Hibernate 库本身所提供的内容和 JDO 必须提供的内容之间的区别。

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

  • 每种方法的优点和缺点是什么?
  • 你对新项目有什么建议?
  • 在什么情况下使用一个框架比使用另一个框架更有意义?
113632 次浏览

一些注意事项:

  • JDO 和 JPA 都是规范,而不是实现。
  • 这个想法是,如果您将代码限制为只使用标准 JPA,那么您可以交换 JPA 实现。(JDO 也是如此。)
  • Hibernate 可以用作 JPA 的这种实现之一。
  • 然而,Hibernate 提供了一个原生 API,其特性超越了 JPA。

我推荐 Hibernate。


有一些关于如果使用特定于 Hibernate 的特性 需要应该做什么的评论/问题。看待这个问题有很多方法,但我的建议是:

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

  • 如果您对供应商绑定的前景感到担忧,并且如果不求助于特定于供应商的扩展就无法使用 JPA,那么就不要使用 JPA。(JDO 也是如此)。

在现实中,您可能需要权衡 多少钱,您担心的是供应商绑定而不是 多少钱,您需要那些特定于供应商的扩展。

还有其他因素,比如你/你的员工对各自的技术了解多少,产品在许可方面的成本是多少,以及你对 JDO 和 JPA 未来的发展有什么看法。

我自己也在研究这个问题,但是找不到两者之间的明显区别。我认为最大的选择是使用哪种实现。就我个人而言,我一直在考虑 DataNucleus平台,因为它是两者的数据存储不可知的实现。

你对新项目有什么建议?

我建议两者都不要使用! 使用 SpringDAO 的 JdbcTemplateStoredProcedureRowMapperRowCallbackHandler一起使用。

我个人使用 Hibernate 的经验是,预先节省的时间远远超过了无休止地花费时间去理解和调试诸如意想不到的级联更新行为等问题。

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

JDO 死了

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

这是在 Apache 下公开开发的。比 JPA 更多的版本,它的 ORM 规范甚至比 JPA2提出的特性还要先进

我使用的是 JPA (来自 Apache 的 OpenJPA 实现,它基于5年以上历史的 KODO JDO 代码库,并且非常快速/可靠)。恕我直言,任何告诉你绕过规格的人都是在给你糟糕的建议。我投入了时间,并得到了肯定的回报。无论使用 JDO 还是 JPA,您都可以以最小的变化更改供应商(JPA 有 orm 映射,所以我们谈论更改供应商不到一天)。如果你有100多张桌子,像我这样做,这是巨大的。另外,您可以通过集群方式的缓存驱逐获得内置的缓存,这很好。SQL/Jdbc 可以用于高性能查询,但透明持久性在编写算法和数据输入例程方面要优于 SQL/Jdbc。我的整个系统中只有大约16个 SQL 查询(50k + 代码行)。

JDO 具有比 JPA 更高级的特性,参见 http://db.apache.org/jdo/jdo_v_jpa.html

我在同一个项目中使用了 Hibernate (JPA 实现)和 JPOX (JDO 实现)。JPOX 工作正常,但是很快就遇到了 bug,其中有些 Java5语言特性当时并不支持。它在处理 XA 事务时存在问题。我正在从 JDO 对象生成数据库模式。它希望每次都能连接到数据库,如果 Oracle 连接发生故障,这会很烦人。

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

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

确保评估了 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

如果你喜欢编写“变通方案”,那么,当然,Hibernate 适合你。如果你喜欢干净、纯粹、面向对象、模型驱动的开发,你会把所有的时间都花在建模、设计和编码上,而不是花在丑陋的解决方案上,那么花几个小时评估 JDO/DataNucleus。投入的时间会得到千倍的回报。

2017年2月更新

很长一段时间以来,DataNucleus 除了 JDO 持久性标准之外,还实现了 JPA 持久性标准,因此将现有的 JPA 项目从 Hibernate 移植到 DataNucleus 应该非常简单,而且只需很少的代码更改(如果有的话) ,就可以获得上述 DataNucleus 的所有好处。 所以就问题而言,选择一个特定的标准,JPA (仅限于 RDBMS) vs JDO (RDBMS + No SQL + ODBMSes + other) ,DataNucleus 同时支持这两个标准,Hibernate 仅限于 JPA。

Hibernate DB 更新的性能

在选择 ORM 时需要考虑的另一个问题是它的脏检查机制的效率——当它需要构造 SQL 来更新当前事务中已经更改的对象时,这一点变得非常重要——尤其是当有很多对象时。 在这个 SO 答案中有关于 Hibernate 脏检查机制的详细技术描述: JPA 与 HIBERNATE 插入非常缓慢

任何声称 JDO 已经死亡的人都是在兜售 FUD,他们知道这一点。

JDO 还活得好好的。该规范仍然比更年轻、更受限制的 JPA 更强大、更成熟、更先进。

如果您希望将自己限制在 JPA 标准中可用的范围内,那么可以写入 JPA,并使用 DataNucleus 作为高性能、比 JPA 的其他实现更透明的持久化实现。当然,如果您希望获得 JDO 带来的建模的灵活性和效率,DataNucleus 也实现了 JDO 标准。

我最近为一个 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 显然还没有死,正如谷歌在 gAE 中采用它并积极开发源代码( http://sourceforge.net/projects/Datanucleus/)所表明的那样。

由于字节码增强,我已经看到了许多关于 JDO 的抱怨,但是还没有解释为什么它不好。

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

我刚开始使用 JDO/Datanucleus,并对它进行了设置,以便在使用 db4o 和 mysql 之间进行轻松切换。使用 db4o 进行快速开发非常有帮助,而且不必过分担心 DB 模式,一旦模式稳定下来,就可以将其部署到数据库中。我还相信,以后我可以将应用程序的全部/部分部署到 GAE,或者利用分布式存储/映射——减少 la hbase/hadoop/Cassandra,而不需要进行太多重构。

我发现开始使用 Datanucleus 的最初障碍有点棘手—— Datanucleus 网站上的文档有点难以理解——教程并不像我希望的那样容易理解。尽管如此,一旦您越过了最初的学习曲线,关于 API 和映射的更详细的文档是非常好的。

答案是,这取决于你想要什么。我更希望有更清晰的代码、无厂商锁定、更面向 pojo、 nosql 选项更流行。

如果您希望获得与大多数其他开发人员/绵羊一样的温暖挑剔感觉,请选择 JPA/hibernate。如果您想在您的领域中领先,那么测试 JDO/Datanucleus 并自己做决定。

我在2012年5月制作了一个使用 JDO 3.0和 DataNucleus 3.0的示例 WebApp ——看看它有多干净: Https://github.com/torbenvesterager/badasswebapp

好吧,也许它有点太干净了,因为我对数据库和 JSON 客户机都使用 POJO,但是它很有趣:)

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