持久层框架JPA与Mybatis该如何选型
一、现状描述
目前java 持久层ORM框架应用最广泛的就是JPA和Mybatis。JPA只是一个ORM框架的规范, 对该规范的实现比较完整就是Spring Data JPA(底层基于Hibernate实现),是基于Spring的数据持久层框架,也就是说它只能用在Spring环境内。Mybatis也是一个优秀的数据持久层框架,能比较好的支持ORM实体关系映射、动态SQL等。
笔者在学习这两个框架的过程中,看过不少的帖子,每当有帖子比较这两个框架的优缺点,就引来一场论战。从笔者的角度,为什么国内的开发人员或者开发团队较少使用JPA?为了避免有人抨击我,我特意去做了一下国内某度指数搜索,这个数据骗不了人。
图中蓝色线条为Mybatis搜索量,绿色为JPA搜索量。如果你换一个国外的搜索指数,你会得到一个完全不同的结果。那么这是为什么呢?我们还要从JPA的特点说起:
- JPA对于单表的或者简单的SQL查询非常友好,甚至可以说非常智能。他为你准备好了大量的拿来即用的持久层操作方法。甚至只要写findByName这样一个接口方法,他就能智能的帮你执行根据名称查找实体类对应的表数据,完全不用写SQL。
- 但是,JPA对于多表关联查询以及动态SQL、自定义SQL等非常不友好。对于JPA来说,一种实现实现方式是QueryDSL,实现的代码是下面这样的。我想问:你希望用这样的代码代替SQL么?
JPAQueryFactory queryFactory = new JPAQueryFactory(em);
JPAQuery<Tuple> jpaQuery = queryFactory.select(QTCity.tCity,QTHotel.tHotel)
.from(QTCity.tCity)
.leftJoin(QTHotel.tHotel)
.on(QTHotel.tHotel.city.longValue().eq(QTCity.tCity.id.longValue()));
//添加查询条件
jpaQuery.where(predicate);
//拿到结果
return jpaQuery.fetch();
另一种方法是使用NativeQuery,我仍然想问:你希望在java代码里面用拼字符串的方式写SQL么?
@Entity
@NamedNativeQueries(value={
@NamedNativeQuery(
name = "studentInfoById",
query = " SELECT * FROM student_info "
+ " WHERE stu_id = ? ",
resultClass = Student.class
)
})
@Table(name="student_info")
以上的这部分实现还没有考虑到动态SQL的问题,如果考虑到动态SQL,写法会更复杂。所谓的动态SQL就是:根据传入参数条件的不同,构造不同的SQL,很多的比较这两个框架的文章都忽略了动态SQL的问题,这方面Mybatis支持的更好。Mybatis写的动态SQL说到底还是SQL,而不是java代码或者java代码拼字符串。程序员特别排斥几件事:
- 将复杂关联关系的SQL写在java代码里面,拼串书写不方便
- SQL是最能表达实体关系查询的语言,程序员不希望使用异化SQL语言。
- 程序员不希望学习不通用的东西,显然SQL大家都会
- JPA虽然将大部分操作封装起来了,也挺好用的,但是SQL调优怎么做?
可以使用Spring-Data-JPA-extra解决JPA的拼串书写和SQL异化的问题。但是根据笔者的使用情况,Spring-Data-JPA-extra是一个个人开发者项目,用于生产还很不成熟,对于多数据源处理、复杂类型处理等还有很多的问题。
二、劣币驱逐良币?
然而,另外有一派观点,你看人家国外的程序员怎么都用JPA?你不去学习新东西,还不让别人用?JPA使用很方便啊,唯一缺点就是复杂关联SQL支持差一点,但是只要你学一下也还可以支持啊,你们这是劣币驱逐良币。如果经过很好的实体关系模型的设计,JPA显然是最优解,程序员写的SQL还真不如JPA根据实体关系生成的SQL。笔者要说,这种观点也是有道理的。但是,笔者要说并不是国内程序员不愿意学习,而是另有原因。
- 首先,笔者长年从事远程工作,与国外程序员接触较多。他们习惯使用JPA的一个原因,真的是因为他们国家的应用规模太小了,比起国内的一个应用动则上百万的用户相比,他们在数据库设计与调优的需求上显然更从容。
- 国外的应用设计往往更简洁,而国内的应用需求往往功能性更强。如果不信,你可以去看看工作流,什么会签、流程回退什么的都是我们发明的,他们没有。你让他们用JPA写一个我们的工作流应用试一试,累吐血他们也做不到。
- 异化SQL或者代码里面写SQL,一定程度上增加了学习成本和使用成本。所以用的人少,用的人少你就得迁就团队中的大部分人。
说完以上几点,Mybatis为什么在国内会有如此多的使用者及使用厂商就不难理解了。Mybatis还可以使用如:Mybatis-plus或者代码自动生成来弥补易用性上的不足。JPA的身材、家室、性格样样都是满分,就是脸长得磕碜点难以处理社交关系。Mybatis虽说在各方面都不优秀,身材还可以、样貌也还说得过去、性格也还好。关键是你说什么都听你的,还有愿意帮他化妆的朋友。要你说你选哪一个?
那么,有的人会说,你这是抬杠?国外就没有受众数量多、功能性强的互联网应用了么?恐怕比国内还多吧,这个也是事实。但是从比例上讲还是国内更多,比例决定开发人员选择技术的方向。这也导致了一个惯性思维,他们平时就用JPA学习训练,所以写大型服务应用的时候也用JPA。那么,他们写JPA会写复杂SQL么?答案是很少会用到,甚至有的国外公司就明令禁止写关联查询SQL。那怎么办?不用关联SQL怎么开发业务需求?不会啊。
三、服务拆分或微服务
国内现在也有越来越多的公司,进行微服务的落地,然而真正落地比较好的企业少之又少。这和多表关联查询有什么关系?我们先来实现这样一个需求:查询属于A角色相关的所有的业务B数据。
- 如果我们开发的是传统的单体应用,我们可能是把角色表A和业务表B进行关联查询,然后得到查询结果
- 如果我们做的是微服务,我们可能是拆分为权限服务A、业务服务B。先去访问A服务接口获取角色标志信息,然后再根据角色标志信息去业务服务B接口获取业务数据。
那么有的人会说,访问两个接口一定比访问一个接口更慢吧!这个真的不是,如果我们做微服务,一定是我们的应用规模及数据量到达了一定程度。也一定会考虑分表分库、负载均衡、服务拆分细化等问题,当分布式的开发方式被应用越多,多表关联查询使用的机会也就越少。拆分后的服务由于功能单一、负载分流等原因,访问速度往往比大数据量数据集中存储、多服务集中部署的应用会快很多。
问题回来了,不用关联SQL怎么开发程序?总的来说就是通过合理的服务拆分、应用的界面数据的组织关系的合理的设计,团队拥有比较好的微服务落地经验,是可以实现不使用关联查询SQL开发应用的。大家也知道,NOSQL越来越流行,绝大部分的NOSQL数据库都没有所谓的关联关系。
四、框架对比选型
对比项 | Spring Data JPA | Mybatis |
---|---|---|
单表操作方式 | 只需继承,代码量极少,非常方便。而且支持方法名用关键字生成SQL | 可以使用代码生成工具或Mybatis-Plus等工具,也很方便,但相对JPA要弱一些。 |
多表关联查询 | 不太友好,动态SQL使用不够方便,而且SQL和代码耦合到一起 | 友好,可以有非常直观的动态SQL |
自定义SQL | SQL写在注解里面,写动态SQL有些费劲 | SQL可以写在XML里面,是书写动态SQL语法利器。也支持注解SQL。 |
学习成本 | 略高 | 较低 ,基本会写SQL就会用 |
总结一下笔者的观点:
- 如果你是自己开发“小而美”的应用,建议你使用JPA
- 如果你是开发大而全的企业级应用,当然要遵从团队的技术选型。这个技术选型在国内通常是Mybatis。
- 如果你们公司的管理非常规范,微服务落地经验也非常成熟,可以考虑在团队项目中使用JPA。少用或不用关联查询。
期待您的关注
- 博主最近新写了一本书:《手摸手教您学习SpringBoot系列-16章97节》
- 本文转载注明出处(必须带连接,不能只转文字):字母哥博客。
持久层框架JPA与Mybatis该如何选型的更多相关文章
- spring boot整合双持久层框架jpa、mybatis
公司之前用的是spring boot + jpa,但由于jpa无法完美的解决某些动态查询问题,就使用的jdbcTemplate 动态封装SQL,由于代码相对复杂,可读性差,现准备再引入mybatis. ...
- MyBatis持久层框架学习之01 MyBatis的起源和发展
一.MyBatis的简介 MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架. MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集. MyB ...
- MyBatis持久层框架使用总结 转载
MyBatis持久层框架使用总结 MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google co ...
- 【持久层框架】- SpringData - JPA
SpringData - JPA 生命不息,写作不止 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 一个有梦有戏的人 @怒放吧德德 分享学习心得,欢迎指正,大家一起学习成长! JPA简 ...
- MyBatis持久层框架使用总结
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis . 2 ...
- java持久层框架mybatis如何防止sql注入
看到一篇很好的文章:http://www.jfox.info/ava-persistence-framework-mybatis-how-to-prevent-sql-injection sql注入大 ...
- 持久层框架之MyBatis
1.mybatis框架介绍: MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并 ...
- spring-boot+mybatis开发实战:如何在spring-boot中使用myabtis持久层框架
前言: 本项目基于maven构建,使用mybatis-spring-boot作为spring-boot项目的持久层框架 spring-boot中使用mybatis持久层框架与原spring项目使用方式 ...
- Java数据持久层框架 MyBatis之背景知识三
摘录自:http://www.cnblogs.com/lcngu/p/5437281.html 对于MyBatis的学习而言,最好去MyBatis的官方文档:http://www.mybatis.or ...
随机推荐
- Python学习笔记整理总结【Django】Ajax
一.Ajax(part1) Ajax即“Asynchronous Javascript And XML”(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术,AJAX = ...
- springboot 启动报错Consider defining a bean of type 'com.example.springbootdruid.mapper.UserMapper' in your configurati
一.问题 springboot项目启动时报错: Field userMapper in com.example.springbootdruid.service.impl.UserServiceImpl ...
- Angular Cli 升级到最新版本
1. 卸载当前版本 npm uninstall -g angular-cli 2. 清除未卸载干净的angular-cli缓存 npm cache clean -f 3. 到安装目录查看是否卸载干净 ...
- Logrotate配置
目录 Logrotate配置 参考 Logrotate Description Logrotate Configuration Logrotate配置
- 使用golang插入mysql性能提升经验
前言 golang可以轻易制造高并发,在某些场景很合适,比如爬虫的时候可以爬的更加高效.但是对应某些场景,如文件读写,数据库访问等IO为瓶颈的场合,就没有什么优势了. 前提基础 1.golang数据库 ...
- python编程基础之六
运算符和表达式 +,-,*,/, 加减乘除 %, 模运算 **, 幂运算 // 整除 运算优先级方面:** >正负号(+,-)>//,%>*,/>+,- 模运算有一 ...
- 最新2019Pycharm安装破解教程!内附破解码!
本教程仅用作个人学习,请勿用于商业获利,造成后果自负!!! Pycharm安装 在这插一个小话题哈,Pycharm只是一个编译器,并不能代替Python,如果要使用Python,还是需要安装Pytho ...
- Kubernetes集群的部署方式及详细步骤
一.部署环境架构以及方式 第一种部署方式 1.针对于master节点 将API Server.etcd.controller-manager.scheduler各组件进行yum install.编译安 ...
- 打造属于自己的 HTML/CSS/JavaScript 实时编辑器
转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者.原文出处:https://blog.bitsrc.io/build-an-html-css-js-playgr ...
- 马蜂窝 IM 移动端架构的从 0 到 1
(马蜂窝技术原创内容,公众号 ID:mfwtech) 移动互联网技术改变了旅游的世界,这个领域过去沉重的信息分销成本被大大降低.用户与服务供应商之间.用户与用户之间的沟通路径逐渐打通,沟通的场景也在不 ...