178

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

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

我很难说出 JPA 规范、您从 Hibernate 库本身获得的内容以及 JDO 必须提供的内容之间的区别。

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

  • 各自的优缺点是什么?
  • 你会为一个新项目推荐哪个?
  • 是否存在某些情况下使用一个框架而不是另一个框架才有意义?
4

11 回答 11

112

一些注意事项:

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

IMO,我会推荐 Hibernate。


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

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

  • 如果您担心与供应商合作的前景,并且如果不求助于供应商特定的扩展就无法使用 JPA,那么请不要使用 JPA。(JDO 同上)。

实际上,您可能需要权衡对供应商绑定的担忧程度与需要这些供应商特定扩展的程度。

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

于 2009-02-09T22:14:19.943 回答
69

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

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

您可能会发现 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 月更新

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

Hibernate DB 更新的性能

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

于 2010-03-11T11:30:29.323 回答
54

我最近评估并选择了一个 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(和 datanucleus 实现)似乎是一个更安全的选择。

我刚刚开始使用 JDO/Datanucleus 并对其进行了设置,以便我可以在使用 db4o 和 mysql 之间轻松切换。使用 db4o 有助于快速开发,而不必过多担心 DB 模式,然后,一旦模式稳定,就可以部署到数据库。我也有信心,以后,我可以将我的全部/部分应用程序部署到 GAE 或利用分布式存储/map-reduce a la hbase /hadoop / cassandra,而无需进行太多重构。

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

答案是,这取决于你想要什么。我宁愿拥有更简洁的代码、无供应商锁定、更面向 pojo、nosql 选项而不是更受欢迎的选项。

如果您想要和大多数其他开发人员/绵羊一样的温暖挑剔感觉,请选择 JPA/hibernate。如果您想在您的领域中处于领先地位,请试用 JDO/Datanucleus 并做出自己的决定。

于 2010-09-27T10:39:07.547 回答
40

你会为一个新项目推荐哪个?

我都不建议!将 Spring DAOJdbcTemplateStoredProcedure, RowMapperand一起使用RowCallbackHandler

我自己对 Hibernate 的个人经验是,预先节省的时间远远超过了您将花费无数天试图理解和调试问题(例如意外的级联更新行为)的时间。

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

于 2009-02-09T22:44:25.910 回答
23

JDO 已死

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

这是在 Apache 下公开开发的。比 JPA 发布的版本更多,其 ORM 规范甚至领先于 JPA2 提议的特性

于 2009-02-21T07:45:36.293 回答
15

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

于 2010-03-10T05:45:24.670 回答
10

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

于 2009-04-16T21:08:57.813 回答
8

我自己一直在研究这个,找不到两者之间的明显区别。我认为最大的选择是您使用哪种实现方式。对于我自己,我一直在考虑DataNucleus平台,因为它是两者的数据存储不可知的实现。

于 2009-02-09T22:29:19.317 回答
8

任何说 JDO 已死的人都是 astroturfing FUD 贩子,他们知道这一点。

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

如果您想将自己限制在 JPA 标准中可用的内容,您可以写入 JPA 并将 DataNucleus 用作比其他 JPA 实现更透明的高性能持久性实现。当然,如果您想要 JDO 带来的建模灵活性和效率,DataNucleus 也实现了 JDO 标准。

于 2010-03-11T11:42:12.717 回答
2

我在同一个项目中使用了 Hibernate(JPA 实现)和 JPOX(JDO 实现)。JPOX 工作正常,但很快就遇到了错误,其中一些 Java 5 语言功能当时不支持。它在处理 XA 事务时遇到了问题。我正在从 JDO 对象生成数据库模式。它每次都想连接到数据库,如果您的 Oracle 连接发生故障,这很烦人。

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

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

于 2010-03-10T06:24:19.997 回答
1

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

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

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

于 2012-11-21T15:42:53.850 回答