乐趣区

关于java:数据持久化框架为什么放弃HibernateJPAMybatis最终选择JDBCTemplate

因为我的项目须要抉择数据长久化框架,看了一下次要几个风行的和不风行的框架,对于简单业务零碎,最终的论断是,JOOQ 是总体上最好的,惋惜不是完全免费,最终抉择 JDBC Template。

Hibernate 和 Mybatis 是应用最多的两个支流框架,而 JOOQ、Ebean 等小众框架则晓得的人不多,但也有很多独特的长处;而 JPA 则是一组 Java 长久层 Api 的标准,Spring Data JPA 是 JPA Repository 的实现,原本和 Hibernate、Mybatis、JOOQ 之类的框架不在同一个档次上,但引入 Spring Data JPA 之类框架之后,咱们会间接应用 JPA 的 API 查问更新数据库,就像咱们应用 Mybatis 一样,所以这里也把 JPA 和其余框架放在一起进行比拟。

同样,JDBC 和其余框架也在同一档次,位于所有长久框架的底层,但咱们有时候也会间接在我的项目中应用 JDBC,而 Spring JDBC Template 局部打消了应用 JDBC 的繁琐细节,升高了应用老本,使得咱们更加违心在我的项目中间接应用 JDBC。

一、SQL 封装和性能

在应用 Hibernate 的时候,咱们查问的是 POJO 实体类,而不再是数据库的表,例如 hql 语句 select count(*) from User,外面的 User 是一个 Java 类,而不是数据库表 User。这合乎 ORM 最后的现实,ORM 认为 Java 程序员应用 OO 的思维形式,和关系数据库的思维形式差距微小,为了填补对象和关系思维形式的鸿沟,必须做一个对象到关系的映射,而后在 Java 的对象世界中,程序员能够应用纯的对象的思维形式,查问 POJO 对象,查问条件是对象属性,不再须要有任何表、字段等关系的概念,这样 java 程序员就更容易做长久层的操作。

JPA 能够视为 Hibernate 的儿子,也继承了这个思路,把 SQL 彻底封装起来,让 Java 程序员看不到关系的概念,用纯的面向对象思维,从新发明一个新的查询语言代替 sql,比方 hql,还有 JPQL 等。反对 JPA 的框架,例如 Ebean 都属于这种类型的框架。

但封装 SQL,应用另一种纯的面向对象查询语言代替 sql,真的可能让程序员更容易实现长久层操作吗?MyBatis 的风行证实了事实并非如此,至多在大多数状况下,应用 hql 并不比应用 sql 简略。首先,从很多角度上看,hql/JPQL 等语言更加简单和难以了解;其次就是性能上明显降低,速度更慢,内存占用微小,而且还不好优化。最为恼火的是,当关系的概念被替换为对象的概念之后,查询语言的灵活性变得很差,表达能力也比 sql 弱很多。写查问语句的时候受到各种各样的限度,一个典型的例子就是多表关联查问。

不论是 hibernate 还是 jpa,表之间的连贯查问,被映射为实体类之间的关联关系,这样,如果两个实体类之间没有(实现)关联关系,你就不能把两个实体(或者表)join 起来查问。这是很恼火的事件,因为咱们很多时候并不需要显式定义两个实体类之间的关联关系就能够实现业务逻辑,如果应用 hql,只是为了 join 咱们就必须在两个实体类之间增加代码,而且还不能逆向工程,如果表外面没有定义外键束缚的话,逆向工程会把咱们增加的关联代码抹掉。

MyBatis 则是另外一种类型的长久化框架,它没有封装 SQL 也没有创立一种新的面相对象的查询语言,而是间接应用 SQL 作为查询语言,只是把后果填入 POJO 对象而已。应用 sql 并不比 hql 和 JPQL 艰难,查问速度快,能够灵便应用任意简单的查问只有数据库反对。从 SQL 封装角度上看,MyBatis 比 Hibernate 和 JPA 胜利,SQL 本不该被封装和暗藏,让 Java 程序员应用 SQL 既不麻烦也更容易学习和上手,这应该是 MyBatis 流行起来的重要起因。

轻量级长久层框架 JOOQ 也和 MyBatis 一样,间接应用 SQL 作为查询语言,比起 MyBatis,JOOQ 尽管知名度要低得多,但 JOOQ 岂但和 MyBatis 一样能够利用 SQL 的灵活性和高效率,通过逆向工程,JOOQ 还能够用 Java 代码来编写 SQL 语句,利用 IDE 的代码主动补全性能,主动提醒表名和字段名,缩小程序员记忆负担,还能够在元数据发生变化时产生编译谬误,提醒程序员批改相应的 SQL 语句。

Ebean 作为一种基于 JPA 的框架,它也应用 JPQL 语言进行查问,少数状况下会让人很恼火。但据说 Ebean 不排挤 SQL,能够间接用 SQL 查问,也能够用相似 JOOQ 的 DSL 形式在代码中结构 SQL 语句(还是 JPQL 语句?),但没用过 Ebean,所以具体细节不分明。

JDBC Template 就不用说了,它基本没做 ORM,当然是纯 SQL 查问。利用 Spring 框架,能够把 JDBC Template 和 JPA 联合起来应用,在 JPA 不好查问的中央,或者效率低不好优化的中央应用 JDBC,缓解了 Hibernate/JPA 封装 SQL 造成的麻烦,但我仍没看到任何封装 SQL 的必要性,除了给程序员带来一大堆麻烦和学习累赘之外,没有太显著的益处。

二、DSL 和变动适应性

为了实现简单的业务逻辑,不论是用 SQL 还是 hql 或者 JPQL,咱们都不得不写很多简略的或者简单的查问语句,ORM 无奈缩小这部分工作,最多是用另一种面向对象格调的语言去表白查问需要,如前所述,用面向对象格调的语言不见得比 SQL 更容易。通常业务零碎中会有很多表,每个表都有很多字段,即使是编写最简略的查问语句也不是一件容易的事件,须要记住数据库中有哪些表,有哪些字段,记住有哪些函数等。写查问语句很多时候成为一件头疼的事件。

QueryDSL、JOOQ、Ebean 甚至 MyBatis 和 JPA 都设计一些个性,帮忙开发人员编写查问语句,有人称之为“DSL 格调数据库编程”。最早实现这类性能的可能是 QueryDSL,把数据库的表构造逆向工程为 java 的类,而后能够让 java 程序员可能用 java 的语法结构出一个简单的查问语句,利用 IDE 的代码主动补全性能,能够主动提醒表名、字段名、查问语句的关键字等,很胜利的简化了查问语句的编写,罢黜了程序员记忆各种名字、函数和关键字的累赘。

QueryDSL 有很多版本,但用得多的是 QueryDSL JPA,能够帮忙开发人员编写 JPQL 语句,如前所述,JPQL 语句有很多局限不如 SQL 灵便高效。起初的 JOOQ 和 Ebean,基本上继承了 QueryDSL 的思路,Ebean 基本上还是 JPA 格调的 ORM 框架,尽管也反对 SQL,但不分明其 DSL 个性是否反对 SQL 语句编写,在官网上看到的例子都是用于结构 JPQL 语句。

这外面最胜利的应该是 JOOQ,和 QueryDSL 不同,JOOQ 的 DSL 编程是帮忙开发人员编写 SQL 语句,摈弃累赘的 ORM 概念,JOOQ 这个性能十分轻小,非常容易学习和应用,同时性能也十分好,不像 QueryDSL 和 Ebean,须要理解简单的 JPA 概念和各种奇怪的限度,JOOQ 编写的就是一般的 SQL 语句,只是把查问后果填充到实体类中(严格说 JOOQ 没有实体类,只是主动生成的 Record 对象),JOOQ 甚至不肯定要把后果转换为实体类,能够让开发人员依照字段获得后果的值,绝对于 JDBC,JOOQ 会把后果值转换为适合的 Java 类型,用起来比 JDBC 更简略。

传统支流的框架对 DSL 格调反对得很少,Hibernate 外面基本上没有看到有这方面的个性。MyBatis 提供了 ”SQL 语句构建器 ” 来帮忙开发人员结构 SQL 语句,但和 QueryDSL/JOOQ/Ebean 差很多,不能提醒表名和字段名,语法也显得累赘不像 SQL。

JPA 给人的印象是简单难懂,它的 MetaModel Api 继承了特点,MetaModel API+Criteria API,再配合 Hibernate JPA 2 Metamodel Generator,让人有点 QueryDSL JPA 的感觉,只是绕了一个大大的弯,叠加了好几层技术,最初勉强实现了 QueryDSL JPA 的简略易懂的性能。很多人不举荐 JPA+QueryDSL 的用法,而是举荐 JPA MetaModel API+Criteria API+Hibernate JPA 2 Metamodel Generator 的用法,让人很难了解,兴许是因为这个计划是纯的规范的 JPA 计划。

数据库 DSL 编程的另一个次要卖点是变动适应性强,数据库表构造在开发过程中通常会频繁发生变化,传统的非 DSL 编程,字段名只是一个字符串,如果字段名或者类型扭转之后,查问语句没有相应批改,编译不会出错,也容易被开发人员疏忽,是 bug 的一个次要起源。DSL 编程外面,字段被逆向工程为一个 java 类的属性,数据库构造扭转之后,作为 java 代码一部分的查问语句会产生编译谬误,提醒开发人员进行批改,能够缩小大量 bug,加重测试的累赘,进步软件的可靠性和品质。

三、跨数据库移植

Hibernate 和 JPA 应用 hql 和 JPQL 这类数据库无关的两头语言形容查问,能够在不同数据库中无缝移植,移植到一个 SQL 有微小差异的数据库通常不须要批改代码或者只须要批改很少的代码。Ebean 如果不应用原生 SQL,而是应用 JPA 的形式开发,也能在不同数据库中平滑的移植。

MyBatis 和 JOOQ 间接应用 SQL,跨数据库移植时都不免要批改 SQL 语句。这方面 MyBatis 比拟差,只有一个动静 SQL 提供的个性,对于不同的数据库编写不同的 sql 语句。

JOOQ 尽管无奈像 Hibernate 和 JPA 那样无缝移植,但比 MyBatis 好很多。JOOQ 的 DSL 很大一部分是通用的,例如分页查问中,Mysql 的 limit/offset 关键字是很不便的形容形式,但 Oracle 和 SQLServer 的 SQL 不反对,如果咱们用 JOOQ 的 DSL 的 limit 和 offset 办法结构 SQL 语句,不批改移植到不反对 limit/offset 的 Oracle 和 SQLServer 上,咱们会发现这些语句还能失常应用,因为 JOOQ 会把 limit/offset 转换成等价的指标数据库的 SQL 语句。JOOQ 依据指标数据库转换 SQL 语句的个性,使得在不同数据库之间移植的时候,只须要批改很少的代码,显著优于 MyBatis。

JDBC Template 应该最差,只能尽量应用规范 sql 语句来缩小移植工作量。

四、安全性

一般来说,拼接查问语句都会有安全隐患,容易被 sql 注入攻打。不论是 jdbc,还是 hql/JPQL,只有应用拼接的查问语句都是不平安的。对于 JDBC 来说,应用参数化的 sql 语句代替拼接,能够解决问题。而 JPA 则应该应用 Criteria API 解决这个问题。

对于 JOOQ 之类的 DSL 格调框架,最终会被 render 为参数化的 sql,天生免疫 sql 注入攻打。Ebean 也反对 DSL 形式编程,也同样免疫 sql 注入攻打。

这是因为 DSL 格调编程参数化查问比拼接字符串查问更简略,没人会拼接字符串。而 jdbc/hql/JPQL 拼接字符串有时候比参数化查问更简略,特地是 jdbc,很多人会偷懒应用不平安的形式。

五、JOOQ 的失败之处

可能大部分人会不批准,尽管 Hibernate、JPA 依然大行其道,是最支流的长久化框架,但其实这种封装 SQL 的纯正 ORM 曾经过期,效益低于应用它们的代价,应该淘汰了。MyBatis 尽管有很多长处,但它的长处 JOOQ 基本上都有,而且少数还更好。MyBatis 最大的毛病是难以避免写 xml 文件,xml 文件编写艰难,容易出错,还不容易查找谬误。绝对于 JOOQ,MyBatis 在少数状况下没有任何劣势。

Ebean 同时具备很多不同框架的长处,但它是基于 JPA 的,不免有 JPA 的各种限度,这是致命的毛病。

JOOQ 这个极其轻量级的框架技术上是最完满的,忽然有一天几个 Web 零碎同时崩了,最初发现是 JOOQ 试用期过期了,这是 JOOQ 的失败之处,它不是完全免费的,只是对 MySql 之类的开源数据库收费。

最终,我决定抉择 JDBC Template。

作者:scherman
起源:segmentfault.com/a/1190000018472572

退出移动版