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

在昨天对比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. 难忘的一天——装操系统(五)
  2. 预训练模型参数重载必备!
  3. Qomo OpenProject beta1 发布!
  4. 重写0-1背包问题的回溯法,使算法能输出最优解
  5. SQLServer优化二
  6. python穷举法_python 穷举指定长度的密码例子
  7. 向量空间相关概念总结-基
  8. 饥荒联机版服务器搭建_Linux 搭建饥荒联机版服务器
  9. 打开matlab只出现蓝色的界面,win10 windows设置无法打开总卡在纯蓝色界面如何解决...
  10. office 所有后缀对应的 content-type
  11. 苹果Mac电脑 如何设置Outlook企业邮箱
  12. CyclicBarrier实现赛马游戏
  13. 用python做一个上位机串口通信_PYTHON制作画加书法源程序
  14. freeRTOS出现任务卡死的情况。
  15. 机器学习/推荐系统/推荐系统算法工程师面试指导
  16. 知识付费内容分类和平台解析
  17. 农村中小学现代远程教育工程情况介绍
  18. SQL Server分组数据
  19. Nginx --高阶
  20. java web 视频开发_Java web video 视频开发

热门文章

  1. python基础数据结构
  2. 【已解决】mac电脑终于卸载掉了这个“微信键盘”输入法
  3. poweriso安装matlab,vmware14 安装 mac10.13
  4. 改变dialog的大小
  5. AJAX、axios、JSONP、CORS
  6. 人气爆棚 加速科技惊艳亮相ICCAD 2021
  7. Excel如何合并单元格并保留全部内容
  8. vscode安装使用,开发python项目环境配置
  9. NetWorkX使用方法及 nx.draw()相关参数
  10. fun(n) c语言,阅读以下函数说明和C语言函数,将应填入(n)的字句写在答题纸的对应栏内。 [说明1] 函数int fun1(in - 赏学吧...