前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >放弃 MyBatis、JPA,我最终选择了 JDBC Template!真香!!

放弃 MyBatis、JPA,我最终选择了 JDBC Template!真香!!

作者头像
Java技术栈
发布于 2021-11-12 02:03:48
发布于 2021-11-12 02:03:48
3.7K0
举报
文章被收录于专栏:Java技术栈Java技术栈

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

因为项目需要选择数据持久化框架,看了一下主要几个流行的和不流行的框架,对于复杂业务系统,最终的结论是,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的必要性,除了给程序员带来一大堆麻烦和学习负担之外,没有太明显的好处。

另外,关注公众号Java技术栈,在后台回复:面试,可以获取我整理的 Java/ MyBatis 系列面试题和答案,非常齐全。

二、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。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-11-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java技术栈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
通过空气质量指数AQI学习统计分析并进行预测(上)
AQI(空气质量指数),用来衡量空气清洁或者污染的程度。值越小,表示空气质量越好。近年来,因为环境问题,空气质量也越来越受到人们的重视。
朱小五
2020/05/26
2.6K0
Python数据分析之数据预处理(数据清洗、数据合并、数据重塑、数据转换)学习笔记
参考链接: Python | pandas 合并merge,联接join和级联concat
用户7886150
2020/12/26
6.2K0
Pandas数据应用:异常检测
在数据分析中,异常检测是一项重要的任务。异常值(也称为离群点)是指与大多数观测值显著不同的数据点。这些异常值可能会影响分析结果的准确性,甚至导致错误结论。Pandas 是 Python 中用于数据分析的强大库,提供了多种方法来检测和处理异常值。本文将由浅入深地介绍常见的异常检测问题、常见报错及如何避免或解决这些问题,并通过代码案例进行解释。
Jimaks
2025/01/06
3390
通过Ti-One机器学习平台玩转2020腾讯广告算法大赛:数据预处理
腾讯的2020腾讯广告算法大赛已经开始快2周了,因为腾讯云有提供优惠卷,所以这总结一下一些基础的操作,帮助大家薅腾讯的羊毛
deephub
2020/05/20
1.5K0
通过Ti-One机器学习平台玩转2020腾讯广告算法大赛:数据预处理
【Python基础系列】常见的数据预处理方法(附代码)
本文简单介绍python中一些常见的数据预处理,包括数据加载、缺失值处理、异常值处理、描述性变量转换为数值型、训练集测试集划分、数据规范化。
Ai学习的老章
2020/08/28
19K0
特征工程与数据预处理全解析:基础技术和代码示例
在机器学习和数据科学的世界里,数据的质量是建模成功与否的关键所在。这就是特征工程和数据预处理发挥作用的地方。本文总结的这些关键步骤可以显著提高模型的性能,获得更准确的预测,我们将深入研究处理异常值、缺失值、编码、特征缩放和特征提取的各种技术。
deephub
2024/07/01
3130
特征工程与数据预处理全解析:基础技术和代码示例
Python数据清洗与预处理面试题解析
数据清洗与预处理是数据分析与机器学习项目中至关重要的环节。面试官往往期望候选人能熟练掌握Python中相关库(如Pandas、NumPy、Scikit-learn等)进行高效的数据清洗与预处理。本篇博客将深入浅出地探讨Python数据清洗与预处理面试中常见的问题、易错点以及如何避免这些问题,同时附上代码示例以供参考。
Jimaks
2024/04/20
3770
数据导入与预处理-第6章-04pandas综合案例
查看数据-运动员信息采集01.csv 数据下载地址: https://download.csdn.net/download/m0_38139250/86789510 下载后解压到工程目录下即可
IT从业者张某某
2022/11/12
9880
数据导入与预处理-第6章-04pandas综合案例
一文读懂!异常检测全攻略!从统计方法到机器学习 ⛵
异常值是偏离数据集中大多数样本点的数据点。出现异常值的原因有很多,例如自然偏差、欺诈活动、人为或系统错误。不过,在我们进行任何统计分析或训练机器学习模型之前,对数据检测和识别异常值都是必不可少的,这个预处理的过程会影响最后的效果。
ShowMeAI
2022/11/29
4.2K0
一文读懂!异常检测全攻略!从统计方法到机器学习 ⛵
使用 Python 进行数据清洗的完整指南
如果你没有听过,那么请记住:数据清洗是数据科学工作流程的基础。机器学习模型会根据你提供的数据执行,混乱的数据会导致性能下降甚至错误的结果,而干净的数据是良好模型性能的先决条件。当然干净的数据并不意味着一直都有好的性能,模型的正确选择(剩余 20%)也很重要,但是没有干净的数据,即使是再强大的模型也无法达到预期的水平。
deephub
2022/04/14
1.3K0
使用 Python 进行数据清洗的完整指南
数据预处理的 10 个小技能,附 Pandas 实现
数据预处理常用的处理步骤,包括找出异常值、处理缺失值、过滤不合适值、去掉重复行、分箱、分组、排名、category转数值等,下面使用 pandas 解决这些最常见的预处理任务。
double
2020/12/02
9440
【无痛学Python】Pandas数据载入与预处理,看这一篇就够了!
对于数据分析而言,数据大部分来源于外部数据,例如CSV文件、Excel文件以及数据库文件等等。
Skrrapper
2025/06/10
1710
Python|一文详解数据预处理
通常获取数据通常都是不完整的,缺失值、零值、异常值等情况的出现导致数据的质量大打折扣,而数据预处理技术就是为了让数据具有更高的可用性而产生的,在本文中让我们学习一下如何用Python进行数据预处理。
数据山谷
2020/08/04
2.9K0
特征工程之异常值处理
工作原理:它是先假设一组检测数据只含有随机误差,对其进行计算处理得到标准偏差, 按一定概率确定一个区间,认为凡超过这个区间的误差,就不属于随机误差而是粗大误差, 含有该误差的数据应予以剔除。
用户3577892
2020/06/11
2.5K1
使用可视化工具和统计方法检测异常值
异常值(离群值)是指距离其他数据值太远的数据值。数据异常值可能是自然产生的,也可能是由于测量不准确、或系统故障造成的。与缺失值类似,异常值会破坏数据科学项目并返回错误的结果或预测。异常值也可能出现在倾斜数据中,这些类型的异常值被认为是自然异常值。
deephub
2022/11/11
4150
使用可视化工具和统计方法检测异常值
数据导入与预处理-课程总结-01~03章
备注:本文主要是课程总结,不做过多的拓展,如果需要详细了解,可以查看本专栏系列内容,专栏链接直达
IT从业者张某某
2022/11/18
3.2K0
数据导入与预处理-课程总结-01~03章
使用可视化工具和统计方法检测异常值
来源:Deephub Imba 本文约2500字,建议阅读7分钟 如果我们在去除异常值之前和之后计算这些统计数据,我们会得到不同的结果。 异常值(离群值)是指距离其他数据值太远的数据值。数据异常值可能是自然产生的,也可能是由于测量不准确、或系统故障造成的。与缺失值类似,异常值会破坏数据科学项目并返回错误的结果或预测。异常值也可能出现在倾斜数据中,这些类型的异常值被认为是自然异常值。 异常值会影响数据的平均值、标准差和四分位范围。如果我们在去除异常值之前和之后计算这些统计数据,我们会得到不同的结果。 异
数据派THU
2022/10/09
8830
使用可视化工具和统计方法检测异常值
图解机器学习特征工程
上图为大家熟悉的机器学习建模流程图(扩展阅读:一文全览机器学习建模流程(Python代码)),整个建模流程非常重要的一步,是对于数据的预处理和特征工程,它很大程度决定了最后建模效果的好坏。
算法进阶
2023/09/01
1.4K0
图解机器学习特征工程
R语言|数据清洗
数据清洗是数据分析流程中必不可少的一步。清洗得当的数据是可靠分析的基础,而在R语言中,有许多强大而灵活的工具可以帮助我们高效完成数据清洗。本文将全面介绍R语言数据清洗的常见技巧,并配以具体的代码示例。
天意生信云
2025/01/22
4210
R语言|数据清洗
【机器学习数据预处理】数据准备
  如果机器学习中用于分析的基础数据有问题,那么基于这些数据分析得到的结论也会变得不可靠。因为对于机器学习而言,只有使用一份高质量的基础数据,才能得到正确、有用的结论,所以有必要进行数据质量校验。数据质量校验的主要任务是检查原始数据中是否存在噪声数据,常见的噪声数据包括不一致的值、缺失值和异常值。
Francek Chen
2025/01/23
3940
【机器学习数据预处理】数据准备
推荐阅读
相关推荐
通过空气质量指数AQI学习统计分析并进行预测(上)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档