Hibernate、iBatis、Java EE 或其他 Java ORM 工具

Posted

技术标签:

【中文标题】Hibernate、iBatis、Java EE 或其他 Java ORM 工具【英文标题】:Hibernate, iBatis, Java EE or other Java ORM tool 【发布时间】:2010-10-17 12:32:01 【问题描述】:

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

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

我想确定 5 个主要比较点

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

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

【问题讨论】:

【参考方案1】:

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

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”)

干杯,罗伯。

【讨论】:

感谢您的建议。我一定会去看看的。 有人知道现实世界的基于 Ebean 的项目吗?这似乎很有趣,我想看看它与通常的 ORM 框架相比如何。【参考方案2】:

我认为我们应该考虑我们使用 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 也不适合构建安全的复杂动态查询。

【讨论】:

【参考方案3】:

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

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

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

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

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

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

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

(添加以回应第一条评论) 如果你有幸重新设计 你的数据库,两个很重要 如果你要成为的考虑因素 使用 ORM:

向所有相关表添加版本号列以支持乐观锁定。 在数据分析期间,确定不可为空的“alternate key”列 开发人员应将其用于hashCode()equals()。不要在这些中使用 PK 列 方法。

【讨论】:

谢谢,这些都是好点。我们正在重新构建应用程序和数据模型,因此它是受先前数据模型和遗留系统功能影响的“相当”的绿地。我希望现在就决定使用 ORM 工具,以免数据模型走得太远。 我在上面添加了几点以回应您的评论。【参考方案4】:

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

【讨论】:

这是一个有趣的用法@vsingh。感谢分享。【参考方案5】:

让我来分析一下。首先,我在Using an ORM or plain SQL? 中写了一些关于这个主题的文章。专门针对您的观点:

学习曲线/易用性

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

分组; 区分类型;和 动态 SQL。

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

另一方面,JPA(包括 Hibernate)试图与 SQL 保持距离,并以对象而不是关系的方式呈现事物。然而,正如 Joel 指出的那样,abstractions are leaky 和 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 中?嗯,这是个问题。

【讨论】:

我认为这确实夸大了 iBATIS 简单的独特性,并低估了在 Java 层中具有业务逻辑的价值。本机查询可以从 JPA 中的文本文件加载和/或作为字符串进行操作——这本质上是 iBATIS。从这个意义上说,我认为 JPA 几乎是一个超集。您可以使用原生查询并将其映射到专门设计的实体,或者迁移到 JPQL 并尝试整合业务逻辑。 & 也许 Oracle Analytics 可以更好地与 iBATIS 集成(我不知道?),但是大多数 Java 容器/服务器现在都支持 JPA,所以我会说它更“标准” ",而不是相反。因此,从某种意义上说,它是轻量级的,至少它是一种广泛可用的依赖项。 @jm0 我认为这是 JPA 的一个缺点,因为当应用服务器提供这些库时,您很容易遇到版本冲突。 是的,公平地说,我只提到了这方面,因为有一段时间我的公司不鼓励包含 lib 以支持使用应用程序服务器默认值。从那以后,我的所有工作都切换到了 Hibernate JPA,并且发现它更便携/功能更强大。我没有遇到与应用程序容器的冲突,这不是一个真正的问题......重新审视这个,我不得不做几个需要在 JPA 中使用字符串构建本机查询的项目,这真的很简单+灵活的。我更喜欢对我现在可以做的所有事情进行建模,并且只使用标准查询。它们在动态 SQL 方面非常聪明。【参考方案6】:

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

您可能想看看Session management using Hibernate in a *multi-threaded* Swing application(或只搜索“休眠多线程”)。

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

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

不管怎样,只要我的 0.02 美元

【讨论】:

感谢您的回答。我们主要做请求/响应类型的工作,但也有一些多线程组件也可以使用一些爱。我很好奇,当您说“使用其他东西可能会更好”时,您有什么建议吗? 抱歉,恐怕不行(但我也很想听听建议;)。延迟加载问题的可能解决方案:如果您已经在使用 Spring,则可以使用 Spring AOP 使用 HibernateInterceptor (jroller.com/kbaum/entry/orm_lazy_initialization_with_dao) 将所有(业务逻辑)方法包装在延迟加载代码路径中。这应该适用于所有需要某种“会话”的 ORM 框架(我认为还有一个 Spring iBatis 拦截器,因此 Spring 开箱即用至少支持 Hibernate 和 iBatis)。【参考方案7】:

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

如果您有一个现有的数据库,那么使用 iBatis 会更好,因为一天后您就可以高效工作,再过两天您就可以了解所有相关信息。

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

【讨论】:

【参考方案8】:

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

【讨论】:

谢谢,没想到。你有使用 JPA 的经验吗?您可以分享的痛苦/收获?【参考方案9】:

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

【讨论】:

我们正在努力建立一个具有持久层的强大对象模型,以从业务逻辑和视图中封装 ORM,以便在需要时可以交换/混合/优化 ORM,而无需过度的影响,同时通过不引入过多的复杂性来保持堆栈的可维护性。 流行语宾果游戏 - 你赢了!您正在引入复杂性,并且一定会产生一些影响,这只是您认为“过度”的问题。【参考方案10】:

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

【讨论】:

但为什么它比 iBatis 或其他解决方案更好? 这不是更好。我的工作水平更高,可能会更难,而且肯定更完整。【参考方案11】:

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

【讨论】:

我们通常“擅长” sql,但我确信其中一个工具会提供一定程度的自动 CRUD 实现收益,而不是手动编写一堆 SQL 和连接管理代码。 这是一个典型的答案。人们认为这是理所当然的,但我还没有看到一些有力的论据证明这一点。这是我与一堆 cmets 就类似主题的博文:yakovfain.javadevelopersjournal.com/… 您的链接不是很有说服力。您似乎错过了 Valery 提出的观点。【参考方案12】:

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

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

【讨论】:

以上是关于Hibernate、iBatis、Java EE 或其他 Java ORM 工具的主要内容,如果未能解决你的问题,请参考以下文章

关于 Java EE、Spring 和 Hibernate

iBatis框架使用 4步曲

Hibernate之环境搭建及demo

SSH:Struts + Spring + Hibernate 轻量级Java EE企业框架

Java EE之Hibernate的HibernateSessionFactory

如何在Java-EE中使用hibernate实现ManyToMany关系?