点击关注公众号,实用技术文章及时了解

在昨天对比ORM框架中,有同学指出JPA狗用了都摇头,看了直接吐血,看来mybatis在国内已经有大一统的趋势了。本篇再次对JPA和mybatis做一个介绍,JPA虽然存在度较低,但确实有很多可取之处,大家可以做一个了解,但该用mybatis还是用着,本篇绝不是引战文。

在我们平时的项目中,大家都知道可以使用 JPA 或者 Mybatis 作为 ORM 层,Jpa是一种规范,hibernate 也是遵从他的规范的。可以简单理解为 Hibernate 是 JPA 的一个实现。

下面看看大精华总结如下(问答观点):

个人认为的最佳回答

首先表达个人观点,JPA必然是首选的。

个人认为仅仅讨论两者使用起来有何区别,何者更加方便,不足以真正的比较这两个框架。

要评判出更加优秀的方案,我觉得可以从软件设计的角度来评判。

个人对 mybatis 并不熟悉,但 JPA 规范和 springdata 的实现,设计理念绝对是超前的。软件开发复杂性的一个解决手段是遵循 DDD(DDD 只是一种手段,但不是唯一手段),而我着重几点来聊聊 JPA 的设计中是如何体现领域驱动设计思想的,抛砖引玉。

聚合根和值对象

领域驱动设计中有两个广为大家熟知的概念,entity(实体)和 value object(值对象)。

entity 的特点是具有生命周期的,有标识的,而值对象是起到一个修饰的作用,其具有不可变性,无标识。在 JPA中 ,需要为数据库的实体类添加 @Entity 注解,相信大家也注意到了,这并不是巧合。

@Entity
@Table(name = "t_order")
public class Order {@Idprivate String oid;@Embeddedprivate CustomerVo customer;@OneToMany(cascade = {CascadeType.ALL}, orphanRemoval = true, fetch = F    etchType.LAZY, mappedBy = "order")private List<OrderItem> orderItems;}

如上述的代码,Order 便是 DDD 中的实体,而 CustomerVo,OrderItem 则是值对象。

程序设计者无需关心数据库如何映射这些字段,因为在 DDD 中,需要做的工作是领域建模,而不是数据建模。实体和值对象的意义不在此展开讨论,但通过此可以初见端倪,JPA 的内涵绝不仅仅是一个 ORM 框架。

仓储

Repository 模式是领域驱动设计中另一个经典的模式。

在早期,我们常常将数据访问层命名为:DAO,而在 SpringData JPA 中,其称之Repository(仓储),

这也不是巧合,而是设计者有意为之。

熟悉 SpringData JPA 的朋友都知道当一个接口继承 JpaRepository 接口之后便自动具备了 一系列常用的数据操作方法,findAll, findOne ,save等。

public interface OrderRepository extends JpaRepository<Order, String>{
}

那么仓储和DAO到底有什么区别呢?这就要提到一些遗留问题,以及一些软件设计方面的因素。在这次SpringForAll 的议题中我能够预想到有很多会强调 SpringData JPA 具有方便可扩展的 API,像下面这样:

public interface OrderRepository extends JpaRepository<Order, String>{findByOrderNoAndXxxx(String orderNo,Xxx xx);@Transactional@Modifying(clearAutomatically = true)@Query("update t_order set order_status =?1 where id=?2")int updateOrderStatusById(String orderStatus, String id);
}

但我要强调的是,这是 SpringData JPA 的妥协,其支持这一特性,并不代表其建议使用。因为这并不符合领域驱动设计的理念。

注意对比

  • SpringData JPA 的设计理念是将 Repository 作为数据仓库,而不是一系列数据库脚本的集合

  • findByOrderNoAndXxxx 方法可以由下面一节要提到的JpaSpecificationExecutor代替,

  • updateOrderStatusById 方法则可以由 findOne + save 代替,不要觉得这变得复杂了,试想一下真正的业务场景,修改操作一般不会只涉及一个字段的修改

  • findOne + save 可以帮助你完成更加复杂业务操作,而不必关心我们该如何编写 SQL 语句

  • 真正做到了面向领域开发,而不是面向数据库 SQL 开发,面向对象的拥趸者也必然会觉得,这更加的 OO。

复杂的多表查询

JPA对复杂 SQL 的支持不好,没有实体关联的两个表要做 join,这也是它最大的诟病,但其设计理念上本身如此:

现代微服务的架构,各个服务之间的数据库是隔离的,跨越很多张表的 join 操作本就不应该交给单一的业务数据库去完成。参考:为什么强烈建议你不要做联表查询?

解决方案是:使用 elasticSearch做视图查询 或者 mongodb 一类的Nosql 去完成。问题本不是问题。

总结

真正走进 JPA,真正走进 SpringData 会发现,我们并不是在解决一个数据库查询问题,并不是在使用一个 ORM 框架,而是真正地在实践领域驱动设计。

(再次补充:DDD 只是一种手段,但不是唯一手段)

spring data jpa 的好处我相信大家都了解,就是开发速度很快,很方便,大家不愿意使用spring data jpa 的地方通常是因为sql 不是自己写的,不可控,复杂查询不好搞,那么下面我要说的就是其实对于这种需求,spring data jpa 是完全支持的!!

@query 注解指定nativeQuery

这样就可以使用原生sql查询了,示例代码来自官方文档:

public interface UserRepository extends JpaRepository<User, Long> {@Query(value = "SELECT * FROM USERS WHERE EMAIL_ADDRESS = ?1", nativeQuery = true)User findByEmailAddress(String emailAddress);
}

结语

你还在担心,使用spring data jpa 会有局限么,他只会加速你的开发速度,并允许你组合使用其他框架,只有好处,没有坏处。。

其他

工作以来一直是使用 hibernate 和 mybatis,总结下来一般传统公司、个人开发喜欢用jpa,互联网公司更青睐于 mybatis。

学习资料:Java进阶视频资源

互联网公司更青睐于 mybatis

  • mybatis 更加灵活。开发迭代模式决定的

  • 传统公司需求迭代速度慢,项目改动小,hibernate可以帮他们做到一劳永逸;

  • 互联网公司追求快速迭代,需求快速变更,灵活的 mybatis 修改起来更加方便,而且一般每一次的改动不会带来性能上的下降

  • hibernate经常因为添加关联关系或者开发者不了解优化导致项目越来越糟糕(本来开始也是性能很好的)

  • mybatis官方文档就说了他是一个半自动化的持久层框架,相对于全自动化的 hibernate 他更加的灵活、可控

  • mybatis 的学习成本低于 hibernate

  • hibernate 使用需要对他有深入的理解,尤其是缓存方面,作为一个持久层框架,性能依然是第一位的。

hibernate 自带三级缓存

  • 一级缓存是默认开启的

  • 二级缓存需要手动开启以及配置优化

  • 三级缓存可以整合业界流行的缓存技术 redis,ecache 等等一起去实现

两个框架比较

  • 从国内开源的应用框架来看,国内使用jpa做orm的人还是比较少,如果换成hibernate还会多一些,所以面临的风险可能就是你会用,和你合作的人不一定会用,如果要多方协作,肯定要考虑这个问题!

  • 灵活性方面,jpa更灵活,包括基本的增删改查、数据关系以及数据库的切换上都比mybatis灵活,但是jpa门槛较高,

  • 更新数据需要先将数据查出来才能进行更新,数据量大的时候,jpa效率会低一些,这时候需要做一些额外的工作去处理!

  • 现在结合Springboot有Springdata jpa给到,很多东西都简化了,感兴趣并且有能力可以考虑在公司内部和圈子里推广

  • 相对来说,jpa的学习成本比mybatis略高

  • 公司业务需求频繁变更导致表结构复杂,此处使用mybatis比jpa更灵活

  • 就方言来讲,一般公司选定数据库后再变更微乎其微,所以此处方言的优势可以忽略

JPA是个全自动化的对象持久化规范,它使得开发人员只需要针对领域模型编写面向对象的代码,而不必关心底层数据存储和SQL查询;而MyBatis则是一个能够灵活编写SQL语句,并将SQL的入参和查询结果映射成POJOs的一个持久层框架。所以,从表面上看,JPA能方便、自动化更强,而MyBatis 在SQL语句编写方面则更灵活自由。

本质上看,JPA是面向对象的,而MyBatis是面向关系的。换言之,JPA是以面向对象的领域模型为中心的,而MyBatis是以数据库为中心的。领域模型致力于解决业务逻辑问题,而关系模型致力于解决数据的高效存取问题。

优缺点比较:

  • JPA/Hibernate更自动化而MyBatis更灵活。

  • 某些情况下,MyBatis性能比JPA/Hibernate更好。

  • JPA支持面向对象的继承概念,支持继承映射、多态关联和多态查询,而MyBatis完全不支持。这一点是MyBatis的最大劣势。

  • MyBatis会助长“以数据库为中心”的设计范式。

另外,没有将Mybatis-Plus纳入对比讨论,Mybatis-Plus托生mybatis,只做增强不做改变,引入了JPA设计思想,称得上集合了jpa和mybatis的优点,是国内大神们的一大经典之作,如果没有MP的横空出世,大量代码堆积在XML中,很难说目前国内ORM中不是jpa占据主流。

附录JVM生态报告

同时,mybatis流行范围主要集中在中日韩

至于日韩为哈也高,大家可以大胆猜猜。

造成ORM框架国内外分割严重局面的原因是什么?、

国人喜欢 Mybatis,而国外流行 JPA 原因分析

国内

1.大厂流行且前期众多中小互联网公司技术领导出于大厂

国内做互联网的 Java 程序很多都是拷贝阿里的,阿里一开始用例 iBatis,大量的老系统都是基于 iBatis/MyBatis 的,市场上对 MyBatis 熟悉的人才更多,招聘和培训更容易,有的青年程序员以为“MyBatis 早已统一全球了”就是一个很好的证明。

2.简单,学习成本低

小公司需要大量入门级的程序员,像大神甚至一个都请不起,请问大神们那些牛 b 框架哪个更快让菜鸟们上手,降低公司学习成本。注意这个成本会一直跟随公司,想必大神们创业直接前后端分离了,毕竟钱嘛多的是。

3.对于复杂性需求的灵活性高

国内绝大部分项目都是面向表结构编程的,把 java 对象仅当成数据容器,查询和模型变更都设计在一张表上,所谓业务逻辑就是一堆增删改查的 sql 集合,当然用 mybatis 方便。

在逻辑不复杂,或者你判断软件生命周期不会超过一年的时候,直接用表结构编程是最方便快捷的。

4.公司环境

国内好多项目都是应付领导的某些奇葩需求。需要面向领导编程。一大半时间其实都是在解决领导的需求。

国内项目需要大量报表统计,需要提供给领导作为决策。看到这里,各位领导不要骂我 ,真的不是黑领导的。

5.Hibernate学习成本高

虽然,实际上 SpringDataJPA 是非常简单的,但是,但是,JPA/Hibernate 后期调试跟踪问题很麻烦,改起来也麻烦。别忘了,牛逼如你的人全公司甚至一个都没。

还有什么缓存什么 Criteria 什么 Lazy,虽然这些你学了也不见得能用上,但一个框架,你不学还是不行的。

6.mybatis-plus加持

这个不多说,mybatis的救星不为过。

国外

1.很多老外对 Mybatis 的认知还停留在 iBatis 阶段

实际上在 Mybatis 的应用场景里面,开发者要的就是自动封装,把 sql 查询结果转化为指定的 java 对象。

这个在 iBatis 阶段,需要开发者自己定义大量的 xml 配置,去指定数据库表字段与 Java 实体类之间的关系。并且,对于每一条 sql,都需要在 xml 中写相应的语句,虽然有代码生成器,带开发量还是不小的。

但 Mybatis 发展到今天,已经非常完美地做好了自动封装数据对象这件事,支持的插件也比较丰富。对于常见的增删改查,也不需要自己写一行代码,这已经无限接近于 Hibernate 的能力了。

2.喜欢 OOP、DDD

认为写 SQL 不优雅,用 jpa 的核心是让我们关注对象建模,而不是关心底层数据库映射。只有你在考虑数据和行为在一起的充血模型、贴身职责,聚合根状态变迁,值对象不变性的情况下,你才会发现 jpa 给你提供了很多便利,根本不需要关注底层存储模型。

在复杂的逻辑、超长的软件生命周期。使用 DDD 的设计方法是目前看比较合理的选择,维护的成本比较低。

DDD 全称是(Domain-Driven Design)这是 2004 年就出来的理论,复杂逻辑的应对之道。DDD 大会在欧洲等地办了一届又一届,CQRS、Event Sourcing 等探索层出不穷,这也是为什么国外比较流行 JPA 原因。

不过,国内主要是随着这两年随着微服务火爆也有人谈起来 DDD 了。但其实 DDD 也不是银弹,需要大拿能把控全局,国内缺的就是这种大拿,搬砖的太多。

3.有些老外在技术选型时,不会考虑除 Spring 这种知名框架外的其他技术,无他,唯手熟尔。

Spring确实很强,国外一个项目,做了几年十几年都是很正常的。我以前接触过一个国外的的电商项目,做了十几年,也跑的好好的,这就是证据。

使用技术也是有惯性的。

4.数据体量和种类没有达到

个人感觉,也咨询了国际友人。老外的项目,在数据体量和种类上完全达不到国内的水平。

所以,他们对于性能上的渴求度没有那么高。追求的是稳定,可维护性好。国内一个双 11,如果用 hibernate,那只能死掉了。

也说明,老外的需求主要是在业务上,技术层面较少考虑。

总之,目前两个框架都非常流行,各有优点,在国内来讲,mybatis流行度超过jpa,但远远不能说jpa狗用了都摇头。

文章观点及信息来源参考:

  • blog.csdn.net/adparking/article/details/118105381

  • blog.csdn.net/u010253246/article/details/105731204

推荐:

主流Java进阶技术(学习资料分享)

PS:因为公众号平台更改了推送规则,如果不想错过内容,记得读完点一下“在看”,加个“星标”,这样每次新文章推送才会第一时间出现在你的订阅列表里。点“在看”支持我们吧!

什么?JPA狗用了都摇头??相关推荐

  1. 狗看了都流泪的Mask-RCNN

    目录 准备数据集: 标注: 将json转换成dataset文件: 将labelme_json中所有的文件归类: mask掩码归类: maskRCNN: 配置要求: 将 ipynb 转 py,查看官方模 ...

  2. 计算机科学与技术单身率,大学里单身率最高的十大专业,单身狗连呼吸都是错!...

    大学里单身率最高的十大专业,单身狗连呼吸都是错! 2019-1-24 15:50:16 | 点击889次 我仍然记得,每个高中老师都说过,"上了大学就轻松了",可轻松是轻松就是没对 ...

  3. 狗拉雪橇都听过,拉卡车的你见过吗?

    编译 | 过客 来源 | 网易科技(公众号ID:tech_163) 4月17日,据英国<每日邮报>报道,波士顿动力公司(以下简称波士顿动力)的机器狗已经不再局限于行走.跳跃和爬楼梯能力.波 ...

  4. 装了win8 之后QQ音乐跟酷狗乐库都显示不出来的问题

    打开IE浏览器-F12 浏览器模式改成IE8 遇到同样问题的朋友可以试一下

  5. 2023王道数据结构P40题二.1,关于是否会断链的问题

    链表在删除一个结点p时为保证不断链,需要在删除前将p的前驱与后继链接起来,即p的前驱的指针域指向p的后继的地址,若将p的前驱记作q,可表示为q->next = p->next,也即为q-& ...

  6. 手把手教你如何Vue项目打包dist文件并Tomcat发布【超级详细】

    ???作者:bug菌 博客:CSDN.掘金等 ??公众号:猿圈奇妙屋 ??特别声明:原创不易,转载请附上原文出处链接和本文声明,谢谢配合. ??版权声明:文章里可能部分文字或者图片来源于互联网或者百度 ...

  7. MySQL的分页你还在使劲的limit?

    MySQL目前常用的分页方式有两种: 1.利用limit实现分页,语法为"SELECT*FROM 表名 limit 开始记录数,每页条数": 2.利用主键索引实现分页,语法为&qu ...

  8. MySQL 查询 limit 1000,10 和 limit 10 速度一样快吗? 深度分页如何破解

    Hollis的新书限时折扣中,一本深入讲解Java基础的干货笔记! 刷网站的时候,我们经常会遇到需要分页查询的场景. 比如下图红框里的翻页功能. 我们很容易能联想到可以用mysql实现. 假设我们的建 ...

  9. MySQL查询 limit 1000,10 和limit 10 速度一样快吗?

    刷网站的时候,我们经常会遇到需要分页查询的场景. 比如下图红框里的翻页功能. 我们很容易能联想到可以用mysql实现. 假设我们的建表sql是这样的 mysql建表sql 建表sql大家也不用扣细节, ...

最新文章

  1. 点击Notification正确回调到之前已经放置在后台的Task中的对应Activity,而不是创建它的一个新实例...
  2. 脱贫利器 | PYTHON多线程行情抓取工具实现
  3. 静态路由中的下一跳地址和送出接口的区别和使用
  4. loadClass和forName 的区别
  5. 一致性 Hash 算法原理总结
  6. python爬取网页版QQ空间,生成词云图、柱状图、折线图(附源码)
  7. python settings模块_Python settings.VERSION属性代码示例
  8. java调用webservice_Oracle触发器调用webservice说明
  9. Project Euler
  10. 图形化服务端svn(win 10)
  11. WebSocket协议:5分钟从入门到精通
  12. 右键文件夹没有git clone命令的解决方法
  13. 面试题,微信朋友圈的“赞”和“评论”为啥是隐藏操作的?
  14. 商城项目测试用例设计实战
  15. STRUTS1框架简介
  16. 思维的误区:忽视沉默的大多数
  17. HSB”、lab、CMYK、RGB有什么区别
  18. secondary namenode详解
  19. 大道至简(周爱民)第一章读后感-------伪代码
  20. DTAS 国产三维尺寸公差分析软件尺寸链计算几何数据导入应用

热门文章

  1. TSRFormer:复杂场景的表格结构识别新利器
  2. 学计算机专业的你后悔了吗? 我在BAT工作多年的心路历程
  3. sql查询没有学生选的课程信息||查询选修了所有课程的学生信息
  4. 计算机中丢失api-ms-win-crt-runtime-l1-1-0.dll
  5. JQ+CSS实现老虎机抽奖效果
  6. 隐马尔可夫模型(HHM)学习笔记3
  7. Excel如何合并单元格并保留全部内容
  8. 各编程语言的应用领域
  9. YUYV 转 RGB 24
  10. 【电源专题】什么是AC/DC转换器