67

我们正在规划一个大型企业应用程序。在经历了 J2EE 的痛苦之后,我们正集中精力评估 hibernate。

看起来新的 Java EE API 更简单。我还阅读了一些关于 Hibernate 和 iBatis 的好东西。我们的团队对任何框架都没有什么经验。

我想确定 5 个主要比较点

  • 学习曲线/易用性
  • 生产率
  • 可维护性/稳定性
  • 性能/可扩展性
  • 易于故障排除

如果您要管理一个由大约 6 名具有 J2EE 经验的开发人员组成的团队,您会使用哪个 ORM 工具,为什么?

4

12 回答 12

112

让我来看看这个。首先,我在Using an ORM or plain SQL? . 专门针对您的观点:

学习曲线/易用性

Ibatis 是关于 SQL 的。如果您了解 SQL,则 ibatis 的学习曲线很简单。Ibatis 在 SQL 之上做了一些事情,例如:

  • 通过...分组;
  • 区分类型;和
  • 动态 SQL。

你仍然需要学习,但最大的障碍是 SQL。

另一方面,JPA(包括 Hibernate)试图与 SQL 保持距离,并以对象而不是关系的方式呈现事物。然而,正如 Joel 所指出的,抽象是有漏洞的,JPA 也不例外。要进行 JPA,您仍然需要了解关系模型、SQL、查询的性能调整等。

Ibatis 只会让您应用您知道或正在学习的 SQL,而 JPA 将要求您了解其他内容:如何配置它(XML 或注释)。我的意思是弄清楚外键关系是某种关系(一对一,一对多或多对多),类型映射等。

如果您了解 SQL,我会说学习 JPA 的障碍实际上更高。如果您不这样做,那么 JPA 的结果就是混合的结果,允许您有效地推迟学习 SQL 一段时间(但它不会无限期地推迟学习)。

使用 JPA,一旦您设置了实体及其关系,其他开发人员就可以简单地使用它们,而无需学习有关配置 JPA 的所有内容。这可能是一个优势,但开发人员仍然需要了解实体管理器、事务管理、托管与非托管对象等。

值得注意的是,JPA 也有自己的查询语言 (JPA-SQL),无论您是否了解 SQL,都需要学习它。您会发现 JPA-SQL 不能做 SQL 可以做的事情的情况。

生产率

这是一个很难判断的。就我个人而言,我认为我在 ibatis 中的工作效率更高,但我对 SQL 也很满意。有些人会争辩说他们使用 Hibernate 的效率更高,但这可能是由于——至少部分是因为不熟悉 SQL。

此外,使用 JPA 的生产力具有欺骗性,因为您偶尔会遇到数据模型或查询的问题,当您打开日志记录并查看您的 JPA 提供程序正在生成和工作的 SQL 时,您需要花费半天到一天的时间来解决输出设置和调用的组合,使其产生既正确又高效的东西。

使用 Ibatis 就没有这种问题,因为您自己编写了 SQL。您可以通过在 PL/SQL Developer、SQL Server Management Studio、Navicat for MySQL 或其他任何工具中运行 SQL 来测试它。查询正确后,您所做的就是映射输入和输出。

我还发现 JPA-QL 比纯 SQL 更尴尬。您需要单独的工具来运行 JPA-QL 查询以查看结果,这是您必须学习的更多内容。实际上,我发现 JPA 的整个部分相当笨拙和笨拙,尽管有些人喜欢它。

可维护性/稳定性

Ibatis 的危险在于扩散,这意味着您的开发团队可能只是在需要时继续添加值对象和查询,而不是寻求重用,而 JPA 每个表都有一个实体,一旦您拥有该实体,就是这样。命名查询倾向于在该实体上进行,因此很难错过。临时查询仍然可以重复,但我认为这不是一个潜在的问题。

然而,这是以刚性为代价的。通常在应用程序中,您需要来自不同表的点点滴滴的数据。使用 SQL 很容易,因为您可以编写单个查询(或少量查询)以一次性获取所有数据并将其放入自定义值对象中。

使用 JPA,您可以将该逻辑上移到您的业务层中。实体基本上全有或全无。现在严格来说这不是真的。各种 JPA 提供程序将允许您部分加载实体等,但即使在那里您谈论的是相同的离散实体。如果您需要来自 4 个表的数据,您要么需要 4 个实体,要么需要将所需的数据组合到业务或表示层中的某种自定义值对象中。

我喜欢 ibatis 的另一件事是您的所有 SQL 都是外部的(在 XML 文件中)。有些人会认为这是一个缺点,但我不是。然后,您可以通过搜索 XML 文件相对容易地找到表和/或列的用途。将 SQL 嵌入代码中(或者根本没有 SQL 的地方)可能会更难找到。您还可以将 SQL 剪切并粘贴到数据库工具中并运行它。这些年来这对我有用多少次,我怎么夸大都不为过。

性能/可扩展性

在这里,我认为 ibatis 胜出。它是直接的 SQL 和低成本。从本质上讲,JPA 根本无法管理相同级别的延迟或吞吐量。现在 JPA 的目标是延迟和吞吐量很少出现问题。然而,高性能系统确实存在,并且倾向于不喜欢 JPA 等更重量级的解决方案。

加上使用 ibatis,您可以编写一个查询,该查询使用您需要的确切列准确返回您想要的数据。从根本上说,JPA 在返回离散实体时无法击败(甚至匹配)它。

易于故障排除

我认为这也是 Ibatis 的胜利。就像我上面提到的,使用 JPA,您有时会花费半天时间来获取查询或实体生成您想要的 SQL,或者诊断事务失败的问题,因为实体管理器试图持久化非托管对象(可能是批处理的一部分)您已经投入了大量工作的工作,因此找到它可能并不容易)。

如果您尝试使用不存在的表或列,它们都会失败,这很好。

其他标准

现在您没有提到可移植性是您的要求之一(意味着在数据库供应商之间移动)。值得注意的是,这里 JPA 有优势。注释的可移植性不如 Hibernate XML(例如标准 JPA 注释没有 Hibernate 的“本机”ID 类型的等效项),但它们都比 ibatis / SQL 更可移植。

此外,我还看到 JPA / Hibernate 用作可移植 DDL 的一种形式,这意味着您运行一个小型 Java 程序,该程序从 JPA 配置创建数据库模式。使用 ibatis,您需要为每个支持的数据库编写一个脚本。

可移植性的缺点是 JPA 在某些方面是最低公分母,这意味着支持的行为在很大程度上是广泛的数据库供应商所支持的常见行为。如果你想在 ibatis 中使用 Oracle Analytics,没问题。在 JPA 中?嗯,这是个问题。

于 2009-04-04T10:51:50.203 回答
11

iBatis 和 Hibernate 之间的一个简单的经验法则是,如果您想要更多的 SQL/关系视图,iBatis 更适合;而对于更复杂的继承链,以及不太直接的 SQL 视图,Hibernate。两者都是广泛使用且可靠的良好框架。所以我认为两者都可能运作良好。也许阅读两者的教程,看看一个听起来是否比另一个好,然后选择一个。

在您列出的内容中,我认为性能差别不大——瓶颈几乎总是数据库,而不是框架。对于其他事情,我认为不同的开发人员会更喜欢其中一个,即没有普遍接受的优先级(对于 iBatis 与 Hibernate)。

于 2009-04-04T05:02:52.413 回答
7

您使用哪种解决方案还取决于您选择(或要求)与 Java EE 规范的兼容程度。JPA 是 Java EE 系统中数据访问的“标准”,因此如果您特别想遵守它,则应该使用它(有一些警告)。

JPA 是对象关系映射系统的标准化。因此,它不提供实现,它只是定义了一种标准化的方法。Hibernate Entity Manager 就是这样一种实现。

由于 JPA 是跨多个供应商的标准,并且由于它仍然相当新,因此它缺少一些在某些用例中有价值的更深奥的功能(例如,用于生成动态 SQL 的 Criteria API)。如果您在需要直接使用 Hibernate 甚至直接使用 JDBC 的情况下使用 JPA 计划。对于这种情况,通用的 DAO 模式非常有用;你可以修改这个:Generic Data Access Objects for use in JPA & JDBC 很容易。

JPA 有一些困难的限制(特别是如果您习惯于 Hibernate),并且对您施加了某些方法,这些方法对于更习惯于编写直接 JDBC 的开发人员来说是困难的。如果您支持将其作为一种方法,请务必做好有关 ORM 与 JDBC 的优缺点的功课。

如果您使用 JPA,一旦您达到学习曲线,它将在简单开发方​​面获得回报(特别是如果您正确实施上述 DAO 模式),而且还可以获得查询结果的多层缓存。如果做得好(我知道这是一个很大的“如果”),我已经看到这提供了可观的好处。

最后,如果你有一个没有什么灵活性的遗留数据模型,那么 Hibernate(和 JPA)会给你带来更多的麻烦,而不是值得。例如:

  • 如果数据库没有候选主键(对于有效的 hashCode 和 equals 实现),您将需要预先分析哪些列唯一地定义了一行——可能很简单,也可能很复杂,具体取决于架构的复杂性;
  • 如果您无法添加版本或时间戳列,您将失去 Hibernate 进行乐观锁定的能力,最终不得不在更新之前进行查询。

(针对第一条评论添加) 如果您有幸重新设计数据库,那么如果您要使用 ORM,有两个非常重要的考虑因素:

  • 为所有相关表添加版本号列以支持乐观锁定。
  • 在您的数据分析期间,决定开发人员应该将其用于&的不可为空的“备用键”列。不要在这些方法中使用 PK 列。hashCode()equals()
于 2009-04-06T18:36:37.637 回答
6

要向列表中添加另一个选项......请查看:

Ebean ORM ( http://ebean-orm.github.io )。

它的主要主张是比 JPA 或 Hibernate 更简单、更直观的编程模型。具体来说,它没有 Hibernate Session 或 JPA EntityManager,没有分离/附加对象(没有合并、持久、刷新),延迟加载正常工作。

...也更易于使用和理解。

您还可以将您自己的 SQL 与 Ebean 一起使用(用于查询、更新、存储过程)和 IMO,它在使用您自己的 SQL 时与 Ibatis 相匹配,易于使用。

如果您希望在 Java SE 中使用 ORM,那么我建议您检查一下。

  • LGPL 许可证
  • 使用 JPA 注释进行映射(@Entity、@OneToMany 等)
  • 无会话 API(没有合并、持久化、刷新 ... save() 和 delete() 代替)
  • “部分对象”支持
  • 大型查询支持(每个对象图持久化上下文)
  • 后台查询
  • 对批处理的良好支持
  • 自动查询调优(通过“Autofetch”)

干杯,罗布。

于 2009-11-11T10:48:15.260 回答
5

我们目前正在开发一个同时使用 Hibernate 和 ibatis 的项目。为什么要使用休眠?它支持我们的领域模型、关系和继承。我们有一个非常复杂的域模型,hiberante 很好地支持它。无需担心编写插入、更新等。Ibatis 仅用于查看。有查询,我们有与查询映射的视图对象(类似于域模型但不是域模型)。Ibatis 在视图对象中返回您想要的数据,而不用担心从结果集中读取,您必须在 Spring JDBC 中进行管理。为什么我们不使用 HQl 或 Spring JDBC 呢?域是如此复杂,在渲染视图时,我们会进行计算、分组和大量的原生 SQL 函数。我们在查询中完成所有这些,使用动态查询,在 ibatis 中管理条件并获得一个干净的轻量级对象。如果您必须遍历多个层以在休眠中获取数据,则更有意义因此,根据您的情况,您可能只想使用一个,两者都使用,也可能不使用。但毫无疑问,hibernate 不是你不能没有的东西。

于 2011-09-13T19:14:18.377 回答
4

请注意,在非平凡的多线程应用程序中使用 JPA/Hibernate(可能还有大多数其他 ORM 解决方案)可以很快成为真正的 PITA,因为数据库会话需要被限制在一个线程中(会话对象不是线程安全的)。添加延迟加载以及持久实体最多可以属于一个活动会话的事实......您将陷入困境......

您可能想看看在*多线程* Swing 应用程序中使用 Hibernate 的会话管理(或仅搜索“休眠多线程”)。

我的经验法则 (YMMV):如果应用程序不适合某种请求/响应周期(例如 Web 服务),那么使用其他东西可能会更好。

当然,另一种解决方案是以规避上述框架限制的方式设计应用程序。更改应用程序的设计以便我可以让框架 XYZ 工作,但会留下不好的回味。

无论如何,只要我的 0.02 美元

于 2010-01-14T14:01:35.023 回答
4

我认为我们应该考虑我们使用 Java(或 OO)的主要原因。

系统必须灵活并允许不断修改规范(这在现实生活中经常发生)。否则我们应该用 C 编程,因为它要快得多。

我认为 Web 应用程序的最佳堆栈将是 Java EE:JPA - EJB - JSF(具有扩展的持久性上下文对话范围)。

JSF 也比纯 JSP/Servlet 慢,但它的开发速度更快。

JPA 更难学习,但开发速度更快(您知道:RAD),并且更改不会产生很大(容易出错的复制粘贴)影响。在您最常用的实体中添加一个新列,您将不得不更新 iBatis 中的所有语句...

JPA 并不是在所有情况下都能很好地工作,但它涵盖了大多数情况,并且它还允许您插入 Native Query 而不是 JPQL,而无需更改任何代码。但是如果你发现自己写了太多的 Native Query,你的项目可能更适合 iBatis。

至于性能,如果你了解事物是如何转换为 SQL 的,JPA 也是高性能的,如果你把它做他最擅长的事情,如果你把它做他不喜欢的事情,它会产生太多的查询. 没有魔法!您必须了解生成的查询,而不是一味地希望在可能出现一些复杂情况时能够采取简单的方法。

此外,如果开发人员拥有 SQL 的所有功能,他们将编写过于复杂的查询来处理业务逻辑,而不是将其放在一个集中的地方,您将在 SQL 中拥有一些业务逻辑,在 EJB 中拥有一些。JPA 应该用于持久化您的模型,而不是用于业务逻辑。

Criteria Query 也不适合构建安全的复杂动态查询。

于 2012-05-24T10:52:38.523 回答
3

如果您确实有一个未开发项目,您可以使用 hibernate,但请注意学习曲线非常陡峭。

如果你有一个现有的数据库,那么使用 iBatis 会好得多,因为一天后你就很有效率,再过两天你就可以了解它了。

您必须考虑的一件事是,休眠条件 api 非常适合创建自定义查询,这取决于您的应用程序,这可能是一个很好的论据。

于 2009-06-08T16:51:32.767 回答
2

如果你没有一个好的对象模型,我看不到 Hibernate 的好处。你当然有 ORM 中的“关系”,因为你有一个关系数据库,但“对象”是关键。没有对象,没有 ORM。我认为对象和表之间的 1:1 映射,没有更丰富的对象行为,并不能证明 ORM 的合理性。如果那是您的情况,请坚持使用 JDBC 或 iBatis。

于 2009-04-04T15:53:38.433 回答
2

我建议使用 JPA 并取决于(严重!)您项目的持续时间/范围,您不妨研究一下 JPA2,因为它提供了 JPA 的一些缺失功能(例如,一个非常好的查询 API)。

于 2009-04-06T18:38:59.707 回答
1

与休眠一起去。您的项目以后肯定会变得更大,并且投资(学习休眠)将以一种或另一种方式得到回报。

于 2009-04-04T12:12:53.737 回答
-2

在决定使用哪一个之前,您是否尝试过回答为什么还要使用 ORM 工具?如果您的团队中有了解 SQL 的人员,请参阅坚持使用 JDBC。

于 2009-04-04T10:56:59.257 回答