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

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

我很难区分 JPA 规范、Hibernate 库本身提供的功能以及 JDO 提供的功能之间的区别。

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

  • 各自的优点和缺点是什么?
  • 您对新项目有何建议?
  • 是否存在某些条件才可以使用一种框架而不是另一种框架?
有帮助吗?

解决方案

一些注意事项:

  • JDO和JPA都是规范,而不是实现。
  • 这个想法是,如果您将代码限制为仅使用标准 JPA,则可以交换 JPA 实现。(JDO 也是如此。)
  • Hibernate 可以用作 JPA 的此类实现之一。
  • 然而,Hibernate 提供了一个本机 API,其功能超越了 JPA。

IMO,我会推荐 Hibernate。


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

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

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

实际上,您可能需要权衡 多少 您担心供应商捆绑与 多少 您需要那些供应商特定的扩展。

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

其他提示

确保评估 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 月更新

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

Hibernate 数据库更新的性能

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

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

我看到的是支持 联合数据组织 主要是:

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

以及支持 日本PA 主要是:

  • 更流行
  • 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,或者利用分布式存储/映射减少 hbase/hadoop/cassandra,而无需太多重构。

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

答案是,这取决于你想要什么。我宁愿有更干净的代码,没有供应商锁定,更面向 pojo,nosql 选项而不是更流行。

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

您对新项目有何建议?

我都不建议!使用 Spring DAO JdbcTemplate 和...一起 StoredProcedure, RowMapperRowCallbackHandler 反而。

我个人使用 Hibernate 的经验是,前期节省的时间远远抵消了您将花费无尽的时间来尝试理解和调试诸如意外的级联更新行为之类的问题。

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

JDO已死

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

这是在 Apache 下公开开发的。比 JPA 发布的版本更多,并且其 ORM 规范甚至仍然领先于 JPA2 提议的功能

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

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

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

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

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

我自己一直在研究这个问题,但找不到两者之间的明显区别。我认为重要的选择是您使用哪种实现。对于我自己来说,我一直在考虑 数据核心 平台,因为它是两者的数据存储无关的实现。

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

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

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

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

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

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top