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

178

我熟悉ORM的概念,几年前在.NET项目中甚至使用过nHibernate; 然而,我没有跟上Java中ORM的话题,并且没有机会使用这些工具。

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

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

因此,我了解到这个问题有点开放式的,但我希望能够得到一些意见:

  • 每种框架的优缺点是什么?
  • 你建议新项目使用哪一种?
  • 是否有某些情况下,使用一种框架比另一种框架更合适?
11个回答

113

一些注释:

  • JDO和JPA都是规范,而不是实现。
  • 如果你将代码限制为仅使用标准JPA,那么你可以交换JPA实现。(JDO类似。)
  • Hibernate可以作为JPA的一种实现。
  • 然而,Hibernate提供了一种本地API,具有超越JPA的功能。

依我之见,我建议使用Hibernate。


有一些评论/问题关于如果你需要使用Hibernate特定的功能该怎么办。有很多看待这个问题的方式,但我的建议是:

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

  • 如果你担心供应商捆绑的前景,并且你不能使用JPA而不采用供应商特定扩展,那么就不要使用JPA。(JDO类似。)

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

还有其他因素,比如你或你的员工对各自技术的了解程度、产品在许可方面的成本以及你相信谁关于JDO和JPA未来会发生什么。


8
工具包,简短明了。值得一提的是,JPA不会阻止使用特定于实现的功能,如果有必要的话。这意味着在Hibernate作为实现时,JPA会允许您使用任何Hibernate特性。 - topchef
23
需要翻译的内容: 一个需要补充的重要说明: 虽然JPA和JDO都对关系型数据库提供了良好的支持,但是JDO是“数据存储器”无关的,因此不局限于关系型数据库领域。随着NoSQL的崛起,人们应该考虑使用避免将其应用程序锁定在传统*SQL世界中的持久性标准。JDO应用程序可以轻松地部署到非关系型数据库存储器上。支持的全部数据存储器列表可在以下网址找到:http://www.datanucleus.org/products/accessplatform/datastores.html - Volksman
2
@Golfman 为什么要基于“可能会发生的事情”做出选择?如果您将来确实需要 NoSQL 支持,那么随时可以转向其他方案……保持简单。 - TM.
1
@Bruno - 当你使用Hibernate的非特定于Hibernate的部分时,你*正在使用JPA。显然,限制自己只使用纯JPA的优点是可以更轻松地切换到另一个JPA实现。 - Stephen C
1
@Stephen C - 我认为Bruno想知道在使用Hibernate特定功能时,JPA提供了什么优势(因为这被声称是JPA的一个好处)。我认为这是个很好的问题,因为我无法想象除了让一些供应商或库能够宣称他们“实现了一个标准”之外,还有什么好处。或者,我应该说,“实现了一个不完整的标准”?我的意思是,光为了使用规范而使用规范是没有意义的。 - Manius
显示剩余7条评论

69
确保您评估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持久化标准,因此从Hibernate移植现有的JPA项目到DataNucleus应该非常简单,您可以获得上述提到的所有DataNucleus的好处,如果有的话,代码更改也很少。 因此,在选择特定标准(JPA(仅关系数据库)与JDO(关系数据库+No SQL + ODBMSes +其他))方面,DataNucleus支持两者,Hibernate仅限于JPA。
Hibernate DB更新的性能
在选择ORM时考虑的另一个问题是其脏检查机制的效率——当需要构造SQL来更新当前事务中已更改的对象时,这一点变得非常重要——特别是当有许多对象时。有关Hibernate的脏检查机制的详细技术描述,请参见此SO答案: JPA with HIBERNATE insert very slow

3
正如我们所知,增强正是JDO被大规模采用的原因! - Pascal Thivent
15
早期Hibernate关键人物针对JDO所进行的大肆宣传的恐吓、假草根运动,无疑是不诚实和令人作呕的。这些行为对JDO的采用肯定产生了一定影响。如今的开发人员知道字节码增强根本不是问题,而且通常会将其用于许多不同于持久化的目的。新的ASM字节码增强库非常快速,你甚至来不及喘口气就完成了。 - Volksman
7
从一开始就预测到了JDO的失败 (http://www.javalobby.org/forums/thread.jspa?forumID=46&threadID=1326),在Hibernate之前,因此不能责怪Hibernate。 Hibernate/Toplink成功地取代了Sun和JDO玩家(以及他们的OODBMS),因为它们是当时更好的答案,而不是因为营销和虚假信息。无论ASM今天有多快,当需要它的时候,5年前并没有出现,而JDO则输掉了这场战斗。 JDO在概念上优越?太糟糕了,它未能及时获得胜利的实现(由于JPA,它也不会回来了)。 - Pascal Thivent
7
这绝对不像过去,以前会有至少17篇不同的反对Hibernate的帖子(但只来自3个不同的IP地址。大家算一下=))。 - Volksman
2
痛苦是一种非常主观的感受:有些人可能认为在编译后等待额外1或2秒钟进行增强处理(现在比以前快一个数量级)是痛苦的,而其他人可能会认为在使用不完全透明的持久性解决方案时对他们的设计/建模和编码施加限制和约束更加痛苦,这取决于其领域模型的表达能力和复杂性,需要花费更多时间来解决所施加的限制。我个人发现后者更加痛苦。不同的人有不同的痛苦。 - Volksman
显示剩余5条评论

54

我最近为一个Java项目评估并选择了一个持久化框架,我的研究结果如下:

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

  • 您可以使用非SQL数据源,例如db4o、hbase、ldap、bigtable、couchdb(用于cassandra的插件)等。
  • 您可以轻松地在SQL和非SQL数据源之间切换。
  • 没有代理对象,因此与hashcode()和equals()实现相关的麻烦较少。
  • 更多POJO,因此需要较少的解决方法。
  • 支持更多关系和字段类型。

而支持JPA的主要原因是:

  • 更受欢迎。
  • JDO已经死亡。
  • 不使用字节码增强。

我发现很多JPA开发人员撰写的文章都是偏向JPA的,他们清楚地没有使用过JDO/Datanucleus,并提出了不使用JDO的薄弱论点。

我还看到很多从JDO用户迁移到JPA后感觉更加满意的文章。

关于JPA更受欢迎,似乎部分原因是由于关系数据库管理系统供应商的支持,而不是它在技术上更加优越。(听起来像VHS/Betamax之争)

JDO及其参考实现Datanucleus显然并没有死亡,谷歌采用了它作为GAE的持久化框架,并对源代码进行了积极开发(http://sourceforge.net/projects/datanucleus/)。

我看到很多关于JDO的投诉,主要是由于字节码增强,但尚未解释为什么这样做是不好的。

事实上,在一个越来越着迷于NoSQL解决方案的世界中,JDO(和Datanucleus实现)似乎是一个更安全的选择。

我刚开始使用JDO/Datanucleus,并且已经设置好了可以轻松地在db4o和mysql之间切换。对于快速开发来说,使用db4o非常有帮助,不需要过多地担心数据库模式,一旦模式稳定下来,就可以部署到数据库中。我还有信心,在以后的时间里,能够将我的应用程序全部或部分部署到GAE,或利用分布式存储/map-reduce,例如hbase/hadoop/cassandra等,而不需要太多重构。

我发现最初开始使用Datanucleus有点棘手- Datanucleus网站上的文档不太容易入手- 教程不如我所希望的那样容易跟随。话虽如此,一旦你克服了最初的学习曲线,API和映射方面更详细的文档非常不错。

答案取决于你想要什么。我更喜欢更干净的代码,没有供应商锁定,更面向对象化的,与nosql选项相比更受欢迎。

如果你想获得与大多数其他开发人员/羊相同的温暖和融洽的感觉,请选择JPA/hibernate。如果你想在自己的领域中处于领先地位,请试用JDO/Datanucleus并自己做决定。


9
实际上,就像我说的那样,我只是在尝试选择解决方案时提供了我的印象。是的,我是Java的初学者,但这与什么相关呢?相反,你已经发表了多次言论,声称JDO已死,却没有提供任何事实或证据来支持这一观点,也没有承认JDO明显优越的技术领域。你显然对JDO/Datanucleus有所成见,并将这些帖子用作维护你的反JDO立场的手段。 - Tom
4
Pascal - 你正在争辩自己陷入困境。我认为你忽略了FAQ中的广告部分的重点。OP询问了有关两种技术的意见。它邀请支持双方的人前来提出他们的建设性批评/建议。对于Andy/Datanucleus和其他JDO用户来强调JDO的优点并防止批评,这与其他人推荐使用Hibernate一样,都不构成广告。 - Tom
5
您最好参考FAQ中的“友善相处”章节,因为您在此话题上的发帖方式指责性强、对抗性强或者非常粗鲁。第一次是关于增强的讽刺性评论;第二次是针对早期实现的困难的抱怨,已经不再相关;第三次是对那些可能不想使用RDBMS的人的儿童般的嘲笑和侮辱;第四次是对持有与您不同观点的人的讽刺嘲笑;第五次是攻击,称呼我为鹦鹉。您认为这样算是“友善相处”吗? - Tom
3
如果您曾经在使用JDO时有过可怕的经历,那么请解释一下具体哪些方面令您感到不满,并承认这可能是早期版本的问题,也许现在已经改进了。同时,您还需要认识到其他人可能有不同的需求。仅仅因为您对JPA感到“满意”,并且想要使用关系数据库管理系统并不意味着其他人也会这样想。也许在追求增加声誉的急切心情下,您已经失去了此声誉应该授予的真正目的?顺便说一句,作为一名开发人员,您确实应该对此类项目的健康状况感兴趣,因为这是推动创新和减少供应商锁定的关键所在。 - Tom
6
这将是我的最后回复 :).. 1. 如果它与问题不相关,为什么要提出?2. 我从未质疑过你的诚实,我说的是你对其他帖子的人不友好,并且自相矛盾。3. 没有人建议你总结8年的经验 - 而是用事实和例子来支持你的陈述,而不是主观陈述很可能会冒犯到别人。5. 在这篇帖子中,“休眠/ JPA / JBoss 是邪恶的”态度在哪里? 我没有看到。我只看到你反对JDO的评论。 - Tom
显示剩余9条评论

40
你会建议新项目使用哪个框架?
我不会建议任何一个!我建议使用Spring DAO的JdbcTemplate与StoredProcedure、RowMapper和RowCallbackHandler一起使用。
我个人使用Hibernate的经验是,前期节省的时间被后续花费在理解和调试问题(例如意外级联更新行为)的无尽日子所抵消。
如果你在使用关系型数据库,那么你的代码与之越接近,你就有更多的控制权。Spring的DAO层允许对映射层进行精细控制,同时消除了样板代码的需要。此外,它集成到Spring的事务层中,这意味着你可以非常容易地添加(通过AOP)复杂的事务行为,而不会干涉你的代码(当然,Hibernate也可以做到这一点)。

4
这显然是反对使用对象关系映射(ORM)的选择,由于自ODBC时代(90年代早期)积累了大量用户和代码库(称之为遗留问题)。除非你选择改用ORM框架,否则没有理由不使用JDBC(与或无Spring)。想想那些有一天决定放弃FORTRAN使用C或Pascal的人。 - topchef
23
@grigory - 我有很多浪费时间去理解Hibernate问题的经验,例如级联更新/删除、查询结构非常低效等。ORM解决方案对于那些对关系数据库了解不足的人来说是一个“快速胜利”。因此,仅了解Hibernate并不可能产生良好的最终产品。根据我的经验,在项目生命周期内,Hibernate(以及ORM)所花费的时间比节省的时间还要多。 - oxbow_lakes
8
很抱歉你在使用Hibernate时遇到了这样糟糕的经历。我自己也是来自于重型数据库/SQL/存储过程/JDBC的学校。我不能说我是个完全的转变者 - 上述每种技术仍然都有它们存在的位置。但对于一般用途的Java 3层应用程序(无论大小),首选的是ORM技术 - 最好是JPA 2。其他因素如遗留代码、集成、专业知识、批量需求、实时性能等会影响(或不会影响)不同的数据库技术栈的选择。 - topchef
3
我完全不同意上面所提到的“快速胜利”定义-只需拿起《Hibernate 实战》(http://stackoverflow.com/questions/96729/what-are-the-best-books-for-hibernate-jpa/96865#96865)(它是 JPA 1,使用 JPA 2 会更好),以完全了解这种技术的功能和覆盖范围。 - topchef
7
我做了一些调查,发现 Spring 不再推荐使用 Spring DAO(http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/orm.html):“推荐的集成方式是根据纯 Hibernate、JPA 和 JDO API 编写 DAO。不再推荐使用旧的 Spring DAO 模板。”……这是你之前推荐的吗?如果是,为什么他们不推荐使用它呢? - User1
显示剩余7条评论

23

JDO已经死了

实际上,JDO没有死,请核实您的事实。 JDO 2.2于2008年10月发布, JDO 2.3正在开发中。

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


12
许多用户使用DataNucleus,更不用说Xcalia和Kodo了,这足以证明人们确实在使用它。您错过了一个基本的概念,即JDO和JPA并没有填补同样的市场。 JPA仅限于关系型数据库(RDBMS),而JDO是数据存储无关的,可用于RDBMS、LDAP、XML、Excel、OODBMs等。 - DataNucleus
3
我喜欢非关系型数据库的因素,特别是随着非关系型数据库解决方案越来越受欢迎,这是一件大事。这意味着如果JPA不足够快速地发展,那么一个“更开放”和灵活的替代品(JDO)的可用性将意味着JPA的流行度会出于必要而趋向下降。不管JDO是否更完整、更优越、更成熟或其他什么技术上的争论——这不会是一个偏好的问题。可以理解为什么关系型数据库供应商会表现得很怀疑——关系型数据库市场的主导地位可能即将结束。 - Manius
我们在2019年仍在使用JDO/DataNucleus!它现在已经升级到5.x版本,对于开发人员的生产力和运行时性能仍然优于Hibernate。最近,我不得不为一个使用Hibernate的大型Web应用程序提供一些咨询服务,并想起了许多年前我作为活跃的Hibernate用户和推广者所遭受的痛苦。一个团队领导不相信我告诉她的BLOB字段总是急切获取,即使它被标记为懒加载。一个“有经验”的自称Hibernate专家完全缺乏“底层”知识,这是令人遗憾但也是预料之中的。 - Volksman

15

非常正确!但似乎没有人知道... - marcolopes

10

我正在使用JPA(Apache的OpenJPA实现,基于KODO JDO代码库,已有5年以上历史,非常快速/可靠)。在我看来,任何建议你绕过规范的人都是在给你错误的建议。我花了时间,确实得到了回报。使用JDO或JPA,您可以在最小的更改下更改供应商(JPA具有ORM映射,因此我们可能只需要一天就能更换供应商)。如果您像我一样有100多个表格,那么这是巨大的优势。此外,您还可以获得集群缓存清除的内置缓存功能,一切都很好。SQL / Jdbc对于高性能查询来说很好,但透明持久性对于编写算法和数据输入例程要优越得多。我的整个系统中只有大约16个SQL查询(50k +行代码)。


8

任何声称JDO已死亡的人都是在宣传FUD,他们心里清楚。

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

如果您想限制自己只使用JPA标准中可用的内容,则可以编写到JPA并使用DataNucleus作为高性能、更透明的持久化实现,而不是JPA的其他实现。当然,如果您想要JDO带来的灵活性和效率,DataNucleus也会实现JDO标准。


1
或者你可以使用另一个(好的)实现,它有一个更大、因此更具响应性的社区。是的,有些人也关心这个。 - Pascal Thivent
1
你在谈论FUD >:) 真有趣。 - Pascal Thivent
2
你的评论似乎假定我没有同时使用过Hibernate和JDO。 - Volksman
2
这个线程似乎有很多人引用了DataNucleus的优点。请不要将此地方作为您的广告平台。 - TM.
3
Golfman在涉及JPA或DataNucleus的每个帖子中都会贴上相同的绝望营销内容,这并不奇怪(他自1996年就开始使用DataNucleus,甚至早于其存在之前!)。 - Pascal Thivent
显示剩余6条评论

8

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


6
支持DataNucleus,不是支持答案。 - WolfmanDragon

2
我曾在同一个项目中使用了Hibernate(JPA实现)和JPOX(JDO实现)。JPOX运行良好,但很快就遇到了一些错误,在当时无法支持一些Java 5语言特性。它在与XA事务协作时存在问题。我是从JDO对象生成数据库模式的,但它每次都想连接数据库,如果你的Oracle连接不起作用,那会很烦人。
然后我们转向Hibernate。我们尝试了一段时间只使用纯JPA,但我们需要使用一些Hibernate特定的功能来进行映射。在多个数据库上运行相同的代码非常容易。Hibernate似乎会积极缓存对象,或者有时具有奇怪的缓存行为。Hibernate无法处理一些DDL结构,因此它们被定义在一个额外的文件中,用于初始化数据库。当我遇到Hibernate问题时,通常有很多人遇到了同样的问题,这使得搜索解决方案更加容易。最后,Hibernate似乎设计得很好,也很可靠。
一些其他回答者建议只使用SQL。对象关系映射的真正杀手级用例是测试和开发。为处理大量数据而构建的数据库通常很昂贵或难以安装。它们很难进行测试。有许多可用于测试的内存Java数据库,但通常对生产无用。能够使用一个真实但有限的数据库将增加开发生产力和代码可靠性。

1
据我所知,JPOX更名为DataNucleus(并且此后已经发布了版本)。 - Donal Fellows
2
你会发现,DataNucleus的未解决bug数量比你提到的其他软件要少得多。而且,你还会发现,与那些软件相比,DataNucleus的开发在更快地减少bug数量。 - DataNucleus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接