持久层框架JPA与Mybatis该如何选型

1、现状描述

目前java 持久层ORM框架应用最普遍的就是JPA和Mybatis。JPA只是一个ORM框架的规范, 对该规范的实现比较完整就是Spring Data JPA(底层基于Hibernate实现),是基于Spring的数据持久层框架,也就是说它只能用在Spring环境内。Mybatis也是一个优秀的数据持久层框架,能比较好的支持ORM实体关系映射、动态SQL等。java

笔者在学习这两个框架的过程当中,看过很多的帖子,每当有帖子比较这两个框架的优缺点,就引来一场论战。从笔者的角度,为何国内的开发人员或者开发团队较少使用JPA?为了不有人抨击我,我特地去作了一下国内某度指数搜索,这个数据骗不了人。程序员

图中蓝色线条为Mybatis搜索量,绿色为JPA搜索量。若是你换一个国外的搜索指数,你会获得一个彻底不一样的结果。那么这是为何呢?咱们还要从JPA的特色提及:spring

  • 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代码拼字符串。程序员特别排斥几件事:springboot

  • 将复杂关联关系的SQL写在java代码里面,拼串书写不方便
  • SQL是最能表达实体关系查询的语言,程序员不但愿使用异化SQL语言。
  • 程序员不但愿学习不通用的东西,显然SQL你们都会
  • JPA虽然将大部分操做封装起来了,也挺好用的,可是SQL调优怎么作?

可使用Spring-Data-JPA-extra解决JPA的拼串书写和SQL异化的问题。可是根据笔者的使用状况,Spring-Data-JPA-extra是一个我的开发者项目,用于生产还很不成熟,对于多数据源处理、复杂类型处理等还有不少的问题。mybatis

2、劣币驱逐良币?

然而,另外有一派观点,你看人家国外的程序员怎么都用JPA?你不去学习新东西,还不让别人用?JPA使用很方便啊,惟一缺点就是复杂关联SQL支持差一点,可是只要你学一下也还能够支持啊,大家这是劣币驱逐良币。若是通过很好的实体关系模型的设计,JPA显然是最优解,程序员写的SQL还真不如JPA根据实体关系生成的SQL。笔者要说,这种观点也是有道理的。可是,笔者要说并非国内程序员不肯意学习,而是另有缘由。负载均衡

  • 首先,笔者终年从事远程工做,与国外程序员接触较多。他们习惯使用JPA的一个缘由,真的是由于他们国家的应用规模过小了,比起国内的一个应用动则上百万的用户相比,他们在数据库设计与调优的需求上显然更从容。
  • 国外的应用设计每每更简洁,而国内的应用需求每每功能性更强。若是不信,你能够去看看工做流,什么会签、流程回退什么的都是咱们发明的,他们没有。你让他们用JPA写一个咱们的工做流应用试一试,累吐血他们也作不到。
  • 异化SQL或者代码里面写SQL,必定程度上增长了学习成本和使用成本。因此用的人少,用的人少你就得迁就团队中的大部分人。

说完以上几点,Mybatis为何在国内会有如此多的使用者及使用厂商就不难理解了。Mybatis还可使用如:Mybatis-plus或者代码自动生成来弥补易用性上的不足。JPA的身材、家室、性格样样都是满分,就是脸长得磕碜点难以处理社交关系。Mybatis虽然说在各方面都不优秀,身材还能够、样貌也还说得过去、性格也还好。关键是你说什么都听你的,还有愿意帮他化妆的朋友。要你说你选哪个?框架

那么,有的人会说,你这是抬杠?国外就没有受众数量多、功能性强的互联网应用了么?恐怕比国内还多吧,这个也是事实。可是从比例上讲仍是国内更多,比例决定开发人员选择技术的方向。这也致使了一个惯性思惟,他们平时就用JPA学习训练,因此写大型服务应用的时候也用JPA。那么,他们写JPA会写复杂SQL么?答案是不多会用到,甚至有的国外公司就明令禁止写关联查询SQL。那怎么办?不用关联SQL怎么开发业务需求?不会啊。数据库设计

3、服务拆分或微服务

国内如今也有愈来愈多的公司,进行微服务的落地,然而真正落地比较好的企业少之又少。这和多表关联查询有什么关系?咱们先来实现这样一个需求:查询属于A角色相关的全部的业务B数据。分布式

  • 若是咱们开发的是传统的单体应用,咱们多是把角色表A和业务表B进行关联查询,而后获得查询结果
  • 若是咱们作的是微服务,咱们多是拆分为权限服务A、业务服务B。先去访问A服务接口获取角色标志信息,而后再根据角色标志信息去业务服务B接口获取业务数据。

那么有的人会说,访问两个接口必定比访问一个接口更慢吧!这个真的不是,若是咱们作微服务,必定是咱们的应用规模及数据量到达了必定程度。也必定会考虑分表分库、负载均衡、服务拆分细化等问题,当分布式的开发方式被应用越多,多表关联查询使用的机会也就越少。拆分后的服务因为功能单1、负载分流等缘由,访问速度每每比大数据量数据集中存储、多服务集中部署的应用会快不少。

问题回来了,不用关联SQL怎么开发程序?总的来讲就是经过合理的服务拆分、应用的界面数据的组织关系的合理的设计,团队拥有比较好的微服务落地经验,是能够实现不使用关联查询SQL开发应用的。你们也知道,NOSQL愈来愈流行,绝大部分的NOSQL数据库都没有所谓的关联关系。

4、框架对比选型

总结一下笔者的观点:

  • 若是你是本身开发“小而美”的应用,建议你使用JPA
  • 若是你是开发大而全的企业级应用,固然要听从团队的技术选型。这个技术选型在国内一般是Mybatis。
  • 若是大家公司的管理很是规范,微服务落地经验也很是成熟,能够考虑在团队项目中使用JPA。少用或不用关联查询。

期待您的关注

相关文章
相关标签/搜索