你更喜欢哪个Java ORM框架?为什么?(ORM指对象关系映射)

295

这是一个相当开放性的问题。我将要开始一个新项目,并正在寻找与数据库访问集成的不同ORM。

你有任何喜欢的吗? 有哪些你建议避免使用?


2
请查看以下重要相关问题:https://dev59.com/VHRB5IYBdhLWcg3w1Kr0#494853 https://dev59.com/KXRB5IYBdhLWcg3wHkPi - ripper234
看一下微ORM - 平台DB访问技术的薄包装器 - 例如Java的sql2o https://github.com/aaberg/sql2o 或.NET的ServiceStack.OrmLite https://github.com/ServiceStack/ServiceStack.OrmLite - tomaszkubacki
3
使用 ORM 超过 5 年后,我个人的选择是 Spring JDBC 而不是 ORM,第二选择是 iBatis(MyBatis),我不喜欢 Hibernate 因为学习曲线高,控制力和性能问题都比较差。 - user4948585
这里有一个(同样关闭的)轻量级JDBC包装器列表,可以作为完整ORM的替代品使用:https://dev59.com/XGw05IYBdhLWcg3wnjAk - Vadzim
10个回答

276

我已经停止使用ORM。

原因不是概念上有任何缺陷。Hibernate运行良好。相反,我发现查询开销很低,可以将大量复杂逻辑嵌入到大型SQL查询中,并将许多处理过程转移到数据库中。

因此,考虑仅使用JDBC包。


95
ORM一直都是一个重复的故事:初始开发很快,但在项目后期追踪ORM相关的错误和低效率将会耗费大量资源。我还讨厌它给开发者们灌输了这样一个观点:他们永远不需要编写特定的优化查询语句。 - Eelco
10
嘿,对于大型实际项目来说,这是否都是真的? - santiagobasulto
32
我同意。我已经使用ORM三年了,我无法描述浪费了多少时间(现在仍然浪费)来解决与持久化相关的问题。我们对于“引擎盖下”发生的事情没有任何控制,配置太多以至于难以有效管理,并且还有一些可能会让人发疯的行为。另一方面,我支持主要数据库并且不必担心它们之间的差异。 - marcolopes
67
为什么不根据查询/交易的复杂程度而选择两者结合使用呢?它们并不是互相排斥的。 - amphibient
8
@WillSheppard 是的Will。我经常使用Django ORM,它非常好用。我认为区别可能在于Python(和Perl)的动态特性。在Java中使用ORM很麻烦,但在动态语言中,它可以表达得非常清晰。有一些出色的项目可以将ORM操作嵌入Python中,例如DSLs,非常棒。 - santiagobasulto
显示剩余10条评论

111

没有,因为使用ORM会带走太多控制权,而带来的好处很小。尽管可以节省时间,但由于使用ORM导致的异常问题需要调试,这些节省的时间很容易就被消耗殆尽。此外,ORM还会阻碍开发者学习SQL以及关系型数据库的工作原理,而这些知识对他们非常有益。


4
我同意这个说法。总开发时间中有多少时间会用于编写持久化代码?我认为不到10-15%。 - adrian.tarau
19
这要看情况。如果您只使用一种特定类型的数据库,那么不使用ORM可能很容易。但是,当您需要支持其他类型的数据库时,情况可能会迅速变得难以管理。 - Jason Baker
4
当使用ORM导致异常时,调试所需的时间节省很容易被抵消。然而,当考虑技能曲线因素选择技术时,这种说法并不一定正确。 - elsadek
9
你的观点可能适用于反对使用任何库。ORM(对象关系映射)的最大优势在于提供了单位操作、对象映射、更改跟踪、惰性加载、迁移和关系等功能。能够编写user.profile.givenName而不必关心用于存储数据的结构是一件很棒的事情。 - Alex
1
哦,我的天啊,我为Java开发人员感到难过。不使用ORM?但也许你是对的,如果在Java世界中没有任何库能够正确工作,并且有176个不同的属性需要设置,那我会感到惊讶。 - EralpB
显示剩余2条评论

99
许多ORM都很好,但你需要知道为什么要在JDBC之上添加抽象层。我可以向您推荐http://www.jooq.org(免责声明:我是jOOQ的创作者,因此这个回答有所偏见)。 jOOQ采用以下范例:
  • SQL很好。许多事情可以在SQL中非常好地表达。没有必要完全抽象化SQL。
  • 关系数据模型很好。它已经被证明是最好的数据模型,持续了40年。无需XML数据库或真正的面向对象数据模型。相反,公司运行着几个Oracle、MySQL、MSSQL、DB2或任何其他RDBMS实例。
  • SQL具有结构和语法。不应使用JDBC中的“低级”字符串连接或HQL中的“高级”字符串连接来表达它们,这两者都容易出现语法错误。
  • 当处理大量查询时,变量绑定往往非常复杂。这是应该抽象化的。
  • 在编写操作数据库数据的Java代码时,POJO很棒。
  • 手动编写和维护POJO非常麻烦。代码生成是一种好方法。您将拥有包括数据类型安全在内的编译时安全的查询。
  • 数据库排第一位。虽然位于数据库之上的应用程序可能会随时间变化而改变,但数据库本身可能会持续更长时间。
  • 是的,您在遗留数据库中有存储过程和用户定义类型(UDT)。您的数据库工具应该支持它们。

还有许多其他好的ORM。特别是Hibernate或iBATIS拥有伟大的社区。但如果您正在寻找一个直观、简单的ORM,我会建议您尝试一下jOOQ。你会喜欢它! :-)

请查看此示例SQL:

  // Select authors with books that are sold out
  SELECT * 
    FROM T_AUTHOR a
   WHERE EXISTS (SELECT 1
                   FROM T_BOOK
                  WHERE T_BOOK.STATUS = 'SOLD OUT'
                    AND T_BOOK.AUTHOR_ID = a.ID);

如何在jOOQ中表达:

  // Alias the author table
  TAuthor a = T_AUTHOR.as("a");

  // Use the aliased table in the select statement
  create.selectFrom(a)
        .whereExists(create.selectOne()
                           .from(T_BOOK)
                           .where(T_BOOK.STATUS.equal(TBookStatus.SOLD_OUT)
                           .and(T_BOOK.AUTHOR_ID.equal(a.ID))))));

1
ORM工具的优劣取决于你是否能正确使用它们。有些项目中,ORM工具可以像魔法一样运作,而在其他项目中,它们可能根本不适用。最终,选择适合项目需求的正确工具是开发团队的责任。ORM工具很复杂。不幸的是,只有部分开发人员会花时间去了解它们的工作原理。其余的人只会责怪工具,并说它不好用。问题是:最受赞同的答案是否提供了最佳建议?
因此,考虑只使用JDBC包。
我们真的想使用纯JDBC吗?
- Vlad Mihalcea
2
我尽量不让“数据库优先”。一个应用程序包含了客户要求的功能的业务规则,而他们几乎从不要求创建数据库。这是在实现过程中确定的技术细节。 - Kwebble
我们真的想使用纯JDBC吗?- 不完全是纯JDBC。但也不远了。你可以用反射来从JDBC ResultSet中填充对象,并使用属性文件来映射数据库表/字段名称,这样你就可以在一两天内创建出一个东西,它就是你所需要的ORM。 - barneypitt

61

Hibernate是Java中事实上的标准,是驱动JPA创建的推动力之一。它在Spring中得到了很好的支持,并且几乎每个Java框架都支持它。最后,GORM是一个非常酷的包装器,使用Groovy进行动态查找等操作。

甚至已经将其移植到.NET(NHibernate),因此您也可以在那里使用它。


4
我也支持使用Hib,但有一个重要的补充:即使Hib提供了JPA实现,我们也应该仅仅使用JPA API。 - Vladimir Dyuzhev

55

Hibernate,因为:

  • 稳定 - 经过多年发展,缺乏任何重大问题
  • 在ORM领域中主导标准
  • 实现了标准(JPA),除了主导它。
  • 在互联网上有大量相关信息。有许多教程、常见问题解决方案等。
  • 功能强大 - 可以将非常复杂的对象模型转换成关系模型。
  • 支持任何主流和中等规模的RDBMS
  • 一旦你学好了,操作起来很容易。

以下是使用ORM的原因:

  • 如果系统设计得好,你会在系统中使用对象。即使使用JDBC,你最终也会编写一些转换层,以便将数据传输到对象中。但我打赌Hibernate比任何自定义解决方案都更擅长转换。
  • 它不会剥夺你的控制权。你可以以非常小的细节来控制事情,如果API没有某些远程功能 - 执行本地查询即可。
  • 任何中等规模或更大的系统如果想要可维护性就不能承受大量查询(无论是在一个地方还是分散在各处)
  • 如果性能不是关键因素。Hibernate会增加性能开销,在某些情况下无法忽略。

当我比较Hibernate和JPA时,我会选择Hibernate;而如果比较JPA和JDO,我会选择JDO!我非常喜欢JDO,但我喜欢Hibernate的两个特性(在JDO中不可用),一个是@Filters,另一个是你可以将版本字段(用于乐观锁定)映射到普通字段中,这在JDO中是不可能的。 - Amir Pashazadeh

33
我建议使用MyBatis。它是JDBC之上的一个薄层,非常容易将对象映射到表格,同时仍然可以使用普通的SQL,一切都在你的掌控之中。

10
对于复杂查询,使用Ibatis;对于新增、更新、删除和简单查询,使用Hibernate是完美的选择。 - darpet

20

在编写一个中等规模的JavaSE应用程序时,我使用Avaje Ebean获得了非常好的体验。

它使用标准JPA注释来定义实体,但提供了一个更简单的API(没有EntityManager或任何附加/分离实体的干扰)。此外,当需要时,它还可以让你轻松地使用SQL查询或者普通的JDBC调用。

它还拥有非常好的流畅且类型安全的查询API。你可以编写如下代码:

List<Person> boys = Ebean.find(Person.class)
                                  .where()
                                       .eq("gender", "M")
                                       .le("age", 18)
                                  .orderBy("firstName")
                                  .findList();

6
我可能有点奇怪... 按照名字的顺序,选择性别为“男性”且年龄小于18岁的人。 对我来说,这看起来好多了 :-) - Eelco
4
这是我在Java中看到的较好的ORM之一。它决定使用单例模式,这使它与其他ORM相比具有巨大的实用优势。 - opsb
我认为你的意思是流畅接口,而不是流体接口。 - Montdidier
@opsb 我认为从技术上讲,它是一个单态而不是单例。 - Montdidier
如何开始使用Avaje Ebean ORM?有任何视频教程吗? - Avinash

12

SimpleORM是一款直截了当且没有魔法的IT技术工具,它在Java代码中定义所有元数据结构,非常灵活。

SimpleORM通过将关系型数据库中的数据映射到内存中的Java对象来提供与Hibernate类似的功能。可以使用Java对象指定查询条件,对象标识符与数据库键保持一致,维护对象之间的关系,并自动将修改后的对象使用乐观锁刷新到数据库中。

但是,与Hibernate不同的是,SimpleORM使用非常简单的对象结构和架构,避免了复杂的解析、字节码处理等操作。SimpleORM体积小,透明度高,只有79K和52K两个大小为的JAR文件,而且只有一个小型可选依赖项(Slf4j)。 (Hibernate加上大约2000K的依赖Jars共计超过2400K。)这使得SimpleORM易于理解,大大降低了技术风险。


我没有使用过它,但ActiveObjects在其网站上自称为一种类似于Hibernate-lite的东西,因此可能存在一些相似之处。 - Abdullah Jibaly

10

Eclipse Link,出于许多原因,特别是我感觉它比其他主流解决方案更少臃肿(至少不是那么显眼的臃肿)。

哦,而且Eclipse Link已经被选为JPA 2.0的参考实现。


5
虽然我分享Java替代自由格式SQL查询的担忧,但我真的认为批评ORM的人是因为应用程序设计通常较差。
真正的OOD由类和关系驱动,ORM提供了不同关系类型和对象的一致映射。如果您使用ORM工具,并以ORM框架支持的任何查询语言(包括但不限于Java表达式树,查询方法,OQL等)编写查询表达式,则绝对做错了什么,即您的类模型很可能无法支持该方式中的要求。干净的应用程序设计实际上不需要在应用程序级别进行查询。我已经重构了许多项目,这些项目最初使用ORM框架的方式与他们习惯的方式一样将SQL字符串常量嵌入其代码中,最终每个人都会惊讶地发现,一旦您将类模型与使用模型匹配起来,整个应用程序变得简单且易于维护。当然,像搜索功能等东西需要查询语言,但即使是这样的查询也受到限制,因此创建甚至更复杂的VIEW并将其映射到只读持久类比在应用程序代码中构建某些查询语言中的表达式要好得多。 VIEW方法还利用了数据库功能,并通过实例化可以比您Java源代码中的任何手写SQL更好地提高性能。因此,我不认为非平凡的应用程序不使用ORM有任何理由。

14
如果您正在使用持久存储构建应用程序(就像我们许多人一样),无论是关系型数据库管理系统(RDBMS)还是某些NoSQL变体,那么该存储将具有自己高效的访问方式。尝试过度抽象化只会导致过度工程化。对“真正的面向对象设计”过于热衷会导致Java所臭名昭著的“太空人架构”。 - Eelco

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