我们正在计划大型的企业应用程序。在经历了J2EE的痛苦之后,我们将重点放在评估休眠状态上。
新的Java EE API看起来更简单。我还阅读了一些有关Hibernate和iBatis的好东西。我们的团队对任何框架都缺乏经验。
我想确定5个主要比较点
- 学习曲线/易用性
- 生产率
- 可维护性/稳定性
- 性能/可伸缩性
- 轻松排除故障
如果您要管理一个由约2名J2EE经验的开发人员组成的团队,那么您将使用哪种ORM工具,为什么呢?
Answers:
让我对此有所了解。首先,我在使用ORM或纯SQL编写了有关此主题的文章。。专门针对您的观点:
学习曲线/易用性
Ibatis与SQL有关。如果您知道SQL,则ibatis的学习曲线很简单。Ibatis在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,适用于MySQL的Navicat中运行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中?好吧,那是个问题。
您选择哪种解决方案还取决于您选择(或要求)与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)将给您带来更多的麻烦,而不是值得的。例如:
(为响应第一条评论而添加) 如果您幸运地重新设计了数据库,那么在要使用ORM时,有两个非常重要的注意事项:
- 将版本号列添加到所有相关表以支持乐观锁定。
- 在数据分析期间,请确定开发人员应为&使用的不可为空的“替代键”列。在那些方法中不要使用PK列。
hashCode()
equals()
要将另一个选项添加到列表中,请看:
Ebean ORM(http://ebean-orm.github.io)。
它的主要主张是比JPA或Hibernate更简单,更直观的编程模型。具体来说,它没有Hibernate Session或JPA EntityManager,没有分离/附加的对象(没有合并,持久化,刷新),延迟加载也可以。
...也更容易使用和理解。
您还可以将自己的SQL与Ebean结合使用(用于查询,更新,存储过程),并且IMO与Ibatis匹配,从而可以使用您自己的SQL轻松使用。
如果您希望在Java SE中使用ORM,那么建议您将其检出。
干杯,罗布。
我们目前正在研究一个同时使用Hibernate和ibatis的项目。为什么要使用休眠模式?它支持我们的域模型,关系和继承。我们有一个非常复杂的域模型,hiberante很好地支持它。无需担心编写插入,更新等问题。Ibatis仅用于查看。有查询,我们有与查询映射的视图对象(类似于域模型,但没有域模型)。Ibatis在所需的视图对象中返回数据,而不必担心从结果集中读取数据,而该结果集必须在Spring JDBC中进行管理。为什么我们不使用HQl或Spring JDBC?这个领域是如此复杂,在渲染view时,我们进行计算,分组和大量本机SQL函数。我们在查询中进行所有操作,使用动态查询,在ibatis中管理条件并获得干净的轻量对象。如果您必须遍历多层才能在休眠状态下获取数据,则更有意义。因此,根据您的情况,您可能只想使用一个,或者两者都使用,也可以不使用。但是绝对可以,休眠不是您不能没有的生活。
请注意,在非平凡的多线程应用程序中使用JPA / Hibernate(以及大多数其他ORM解决方案)可以很快成为真正的PITA,因为数据库会话需要严格限制在一个线程内(Session对象不是线程安全的)。添加延迟加载和持久性实体最多只能属于一个活动会话这一事实...您将一路狂奔...
您可能想看一看在*多线程* Swing应用程序中使用Hibernate进行会话管理(或仅搜索“休眠多线程”)。
我的经验法则(YMMV):如果应用程序不适合某些请求/响应周期(例如Web服务),则使用其他方法可能会更好。
当然,另一种解决方案是以一种避免提到的框架限制的方式设计应用程序。更改应用程序的设计,使我可以使XYZ框架正常工作,但留下了不好的回味。
无论如何,只要$ 0.02
我认为我们应该考虑使用Java(或OO)的主要原因。
该系统必须具有灵活性,并允许不断修改规格(这在现实生活中经常发生)。否则,我们应该使用C编程,因为它要快得多。
我认为Web应用程序的最佳堆栈是Java EE:JPA-EJB-JSF(扩展的持久性上下文对话范围)。
JSF还比纯JSP / Servlet慢,但开发速度更快。JPA并非在所有情况下都能很好地工作,但是它涵盖了大多数情况,它还允许您插入本机查询而不是JPQL,而无需更改任何代码。但是,如果您发现自己编写了太多本机查询,那么您的项目可能更适合iBatis。
JPA较难学习,但开发(您知道:RAD)的速度更快,并且更改不会产生很大的影响(容易出错的复制粘贴)。在最常用的实体中添加新列,然后您将不得不更新iBatis中的所有语句...
至于性能,如果您了解事物如何转换为SQL,并且让它执行他最擅长的事情,或者让JPA做他不满意的事情,那么JPA也会很有效,它将产生过多的查询。没有魔法!您必须了解所生成的查询,而不是盲目希望在某些复杂情况出现时可以采取简单的方法。
同样,如果开发人员拥有SQL的全部功能,他们将编写过于复杂的查询以处理业务逻辑,而不是将其放在一个集中的位置,您将在SQL中拥有一些业务逻辑,而在EJB中则具有一些业务逻辑。JPA应该用于持久化模型,而不是用于业务逻辑。
条件查询也不适合构建安全的nomatterhowcomplex动态查询。
如果您没有好的对象模型,那么我将看不到Hibernate的好处。因为您有关系数据库,所以您在ORM中肯定有“关系”,但是“对象”是关键。没有对象,没有ORM。我认为对象和表之间的1:1映射(没有更丰富的对象行为)不能证明ORM是正确的。如果您遇到这种情况,请坚持使用JDBC或iBatis。
我建议您使用JPA,并(很大程度上取决于)项目的持续时间/范围,您不妨研究一下JPA2,因为它提供了JPA的某些缺少的功能(例如,非常好的Query API)。
在决定使用哪个工具之前,您是否尝试过回答为什么甚至使用ORM工具?如果您的团队中有一些了解SQL的人,请参阅JDBC。