我们正在规划一个大型企业应用程序.在经历了J2EE的痛苦之后,我们将重点放在评估hibernate上.
看起来新的Java EE API更简单.我还读了一些关于Hibernate和iBatis的好东西.我们的团队对任何框架都缺乏经验.
我想确定5个主要的比较点
学习曲线/易用性
生产率
可维护性/稳定性
性能/可扩展性
易于故障排除
如果您要管理一个由具有J2EE经验的约6位开发人员组成的团队,您将使用哪种ORM工具?为什么?
让我对此嗤之以鼻.首先,我在使用ORM或纯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返回离散实体时,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实体管理器就是这样一种实现.
由于JPA是跨多个供应商的标准,并且因为它仍然相当新,它缺少一些在某些用例中有价值的深奥功能(例如,用于生成动态SQL的Criteria API).如果您在需要直接使用Hibernate,甚至直接使用JDBC的情况下使用JPA计划.对于这种情况,通用DAO模式非常有用; 你可以修改这个:通用数据访问对象很容易在JPA和JDBC中使用.
JPA有一些困难的限制(特别是如果你已经习惯了Hibernate),并对你施加某些方法,对于那些习惯于直接编写JDBC的开发人员而言,这些方法很难实现.如果您支持这种方法,请务必做好有关ORM与JDBC的优缺点的功课.
如果你使用JPA,一旦你达到了学习曲线,它将在简单的开发(特别是如果你正确实现上述DAO模式)方面得到回报,而且还可以获得查询结果的多层缓存.如果做得好(我知道这是一个很大的"如果"),我看到这提供了很多好处.
最后,如果你有一个你没有灵活性的遗留数据模型,Hibernate(和JPA)将给你带来比可能值得更多的麻烦.例如:
如果数据库没有候选主键(对于有效的hashCode和equals实现),则需要对哪些列唯一定义行进行前期分析 - 可能很简单,可能很复杂,具体取决于模式的复杂性;
如果您无法添加版本或时间戳列,则会失去Hibernate执行乐观锁定的能力,并最终在更新之前必须进行查询.
(在回复第一条评论时添加) 如果您有幸重新设计数据库,那么如果您要使用ORM,则需要考虑两个非常重要的因素:
将版本号列添加到所有相关表以支持乐观锁定.
在数据分析期间,决定开发人员应用于&的非可空" 备用密钥 "列.不要在这些方法中使用PK列.
hashCode()
equals()
要向列表添加其他选项...请查看:
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(没有合并,持久,刷新...另存储()和删除()
"部分对象"支持
大查询支持(每个对象图持久化上下文)
背景查询
良好的批处理支持
自动查询调整(通过"自动提取")
干杯,罗布.
我们目前正在开发一个同时使用Hibernate和ibatis的项目.为什么要使用hibernate?它支持我们的域模型,关系和继承.我们有一个非常复杂的域模型,而hiberante非常支持它.无需担心编写插入,更新等.Ibatis仅用于视图.有查询,我们有视图对象(类似于域模型,但不是域模型)与查询映射.Ibatis在您想要的视图obejct中返回数据,而不必担心从结果集中读取,您必须在Spring JDBC中管理它.为什么我们不使用HQl或Spring JDBC?域是如此复杂,在渲染视图时,我们进行计算,分组和大量本机SQL函数.我们在查询中执行所有操作,使用动态查询,管理ibatis中的条件并获得干净的轻量级对象.如果你必须遍历多个层以在休眠中获取数据,那么更有意义因此,根据您的情况,您可能只想使用一个,两者都可以,或者可以不使用.但绝对是,hibernate不是你不能没有的东西.