繁体   English   中英

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

[英]Hibernate, iBatis, Java EE or other Java ORM tool

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

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

我想确定 5 个主要的比较点

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

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

让我来看看这个。 首先,我在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 中? 嗯,这是个问题。

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

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

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

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

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

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

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

最后,如果你有一个遗留数据模型,你几乎没有灵活性,Hibernate(和 JPA)会给你带来更多的麻烦。 例如:

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

(针对第一条评论添加)如果您有幸重新设计了数据库,那么如果您打算使用 ORM,则有两个非常重要的注意事项:

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

要将另一个选项添加到列表中...看看:

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

干杯,罗伯。

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

我认为我们应该考虑使用 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 也无法构建安全的 nomatterhowcomplex 动态查询。

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

您可能想看看在*多线程* Swing 应用程序中使用Hibernate 的会话管理(或者只是搜索“hibernate multi-threaded”)。

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

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

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

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

如果您有一个现有的数据库,那么使用 iBatis 会好得多,因为一天后您的工作效率很高,两天后您就可以了解它的全部内容。

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM