点击关注上方“Java技术江湖”,设为“置顶或星标”,第一时间送达技术干货。
不要以为MyBatis更方便,如果只是用一些简单1+1=2,MyBatis会很简单,但当业务实体之间存在复杂的关联、继承关系时,MyBatis的结果集映射会就比较繁琐了。
技术潮流往往一波一波的:初中级开发者往往被裹夹其中,随波逐流,但这些人往往嗓门最大。十多年前,Hibernate如火如荼时,初中级开发者高呼:有了Hibernate,就不再需要JDBC、iBatis(后更名为MyBatis)了;现在,又换了另一波初中级开发者高呼:Hibernate已死,MyBatis才强大!
正如十多年前,我呼吁大家可以花点时间关注JDBC本身、iBatis一样,从那时候起,我就一直重复:Hibernate只是对JDBC的封装,如果不能精通JDBC,盲目使用Hibernate会带来致命的性能问题:
关联关系的1+N的性能陷阱?
延迟加载的性能差异?何时应该使用延迟加载?何时应该关闭延迟加载?
更新之前执行数据检查如何影响性能?
如何控制Hibernate生成高效的SQL?
二级缓存、查询缓存如何优化?
如果这些问题不能好好地理顺,盲目地依靠Hibernate去执行持久化操作,肯定会在项目中引入严重的性能陷阱。
这些原来以为Hibernate上手简单的初中级开发者,当他用熟之后往往才会发现Hibernate“很难驯服”,此时他们就会陷入对Hibernate的恐惧,转投MyBatis的怀抱。
现在,有些开发者对MyBatis的掌握,完全停留在简单的ResultSet映射上,对MyBatis的复杂一点的用法尚不熟悉,至于MyBatis底层运行机制、原理更是一无所知——这些人之所以推崇MyBatis,同样是因为MyBatis上手快。
但问题是:在编程世界里,哪个Hello world不简单呢?就像算术中1+1=2当然简单了,但你应该知道还有1+2=3,还有乘法、还有除法——
因此,对于那些只能简单使用MyBatis、连MyBatis官方文档都没能认真撸一遍的开发者而言,本文并不适合!因为本文要介绍的场景比MyBatis的官方文档的示例要复杂一些。
现在,我希望花点时间来对比一下MyBatis与Hibernate的在“关联查询”、“多态查询”上的的差异,希望让广大一知半解的初中级开发者清醒一点。
业务场景
本文用的实例包括4个实体类,这些实体类之间不仅存在继承关系,也存在复杂的关联关系。
本示例中一共包括Person、Employee、Manager、Customer四个实体类,其中Person持久化类还包含一个Address组件属性。
上面4个持久化类之间的继承关系是:Person派生出了Employee和Customer,而Employee又派生出了Manager。
上面4个实体之间的关联关系是:Employee和Manager之间存在双向的N-1关联关系,Employee和Customer之间存在双向的1-N关联关系。
图1显示了这4个实体之间的关系。
![3b2fb873fe47079bb5f7847e9135b6fd.png](https://img-blog.csdnimg.cn/img_convert/3b2fb873fe47079bb5f7847e9135b6fd.png)
图1 4个实体之间的关联、继承关系
上面4个实体中,Person实体包含了一个Address复合属性,Address类比较简单,它就是一个普通的JavaBean。该类的代码如下:
public class Address{
// 定义代表该Address详细信息的成员变量 private String detail; // 定义代表该Address邮编信息的成员变量 private String zip; // 定义代表该Address国家信息的成员变量 private String country; // 无参数的构造器 public Address() {
} // 初始化全部成员变量的构造器 public Address(String detail , String zi