mybatis 的加载与缓存
在这里我要说一下 我没有亲自去敲案例只是看了 我兄弟的文档 在这里和大家说一下
延迟加载:
所谓延迟加载是什么?
从字面意思理解到的是等一会再加载
从行为分析,他主要是缓解数据库压力,提高性能的意义
所谓延迟加载可以做到,我访问你的时候,我用到你的时候,你再做加载
延迟加载用在关联查询的多条SQL语句上
延迟加载的分类:
直接加载------------》(默认的)这个由于是默认的,所以这个可以不做配置
侵入式延迟加载------------》(需要配置)在执行完第一条sql时候,得到一个对象,没有访问这个对象的任何属性时,不会走第二条SQL,也就是不加载这个对象里包含的其他对象
深度延迟加载--------》(需要配置)在执行完第一条sql时候,得到一个对象,即使访问到这个对象的属性,只要不是那个关联的对象,也不会走第二条sql,当访问这个关联的对象时,走第二条sql,
给这个对象拿到值
下面我把实现延迟加载的方式放到下面,并做小实验,证明我上面说的话
实体类
1 //Dept类import java.util.ArrayList; 2 import java.util.List; 3 /** 4 * Created by Dawn on 2018/2/26. 5 */public class Dept { 6 private Integer deptNo; 7 private String deptName; 8 private List<Emp> emps=new ArrayList<Emp>(); 9 10 public Integer getDeptNo() { 11 return deptNo; 12 } 13 14 public void setDeptNo(Integer deptNo) { 15 this.deptNo = deptNo; 16 } 17 18 public String getDeptName() { 19 return deptName; 20 } 21 22 public void setDeptName(String deptName) { 23 this.deptName = deptName; 24 } 25 26 public List<Emp> getEmps() { 27 return emps; 28 } 29 30 public void setEmps(List<Emp> emps) { 31 this.emps = emps; 32 } 33 }
1 //emp类package cn.dawn.demo04.entity; 2 3 import cn.dawn.demo04.entity.Dept; 4 /** 5 * Created by Dawn on 2018/2/26. 6 */public class Emp{ 7 private Integer empNo; 8 private String empName; 9 private Integer deptNo; 10 private Dept dept; 11 12 public Dept getDept() { 13 return dept; 14 } 15 16 public void setDept(Dept dept) { 17 this.dept = dept; 18 } 19 20 public Integer getEmpNo() { 21 return empNo; 22 } 23 24 public void setEmpNo(Integer empNo) { 25 this.empNo = empNo; 26 } 27 28 public String getEmpName() { 29 return empName; 30 } 31 32 public void setEmpName(String empName) { 33 this.empName = empName; 34 } 35 36 public Integer getDeptNo() { 37 return deptNo; 38 } 39 40 public void setDeptNo(Integer deptNo) { 41 this.deptNo = deptNo; 42 } 43 }
接口中使用的方法也就是个简单的根据部门编号返回该部门下全部员工的信息
关注点不在这个方法,而在于一会怎么实现延迟加载和延迟加载的实际效果
/*一对多多条sql*//*延迟加载*/
public Dept findDeptnoALLEmpsMoreSql(Integer deptNo);
接口同名的xml小配置中的代码我也放上去
1 <!--一对多多条sql--><!--延迟加载--><!--缓存--> 2 <resultMap id="DeptMoreSqlMapper" type="Dept"> 3 <id column="deptNo" property="deptNo"></id> 4 <result column="deptName" property="deptName"></result> 5 <collection property="emps" ofType="Emp" select="findDeptnoALLEmpsMoreSqlEmps" column="deptNo"> 6 <id column="empNo" property="empNo"></id> 7 <result column="empName" property="empName"></result> 8 </collection> 9 </resultMap> 10 <!--一对多多条sql--><!--延迟加载--> 11 <select id="findDeptnoALLEmpsMoreSql" resultMap="DeptMoreSqlMapper"> 12 SELECT deptNo,deptName FROM dept WHERE deptNo=#{deptNo} 13 </select> 14 <select id="findDeptnoALLEmpsMoreSqlEmps" resultType="Emp"> 15 SELECT * FROM emp where deptNo=#{deptNo} 16 </select>
lazyLoadingEnabled是延迟加载的开关,默认值是false,不开启,也就是直接加载————————》不要提有些mybatis的api,他里面写错了,你可以去试试
aggressiveLazyLoading是侵入式的开关,默认值是true,开启,如果设置为false,则是深度加载的配置方法,侵入和深度使用有个前提,就是延迟加载的开关要开启,即lazyLoadingEnabled为true
测试方法,我会把对应的延迟加载的配置放开,并附上运行结果,然后解释它
直接加载略,简单讲述一下,就是大配置中的所有setting中的延迟配置都不用配,他只要调用该dao层的方法,就发送俩条sql,把所有查出来
侵入式延迟加载,首先把对应的配置打开(即上面我说的那处,你把我写的那个注释取消掉)
运行结果
用了logback日志监控sql语句,发现在分割线下还有sql在执行了一遍,这就是我上面说的,侵入式延迟加载,在访问这个对象的任何属性时,才会走第二条sql,加载出这个对象里面关联的实体类的
这结果印证了我上面说的一句话,深度延迟,不访问这个对象的关联的那个对象集合时候,不做关联查询操作,不发第二条sql,一旦用到关联的那个对象集合的时候,他就做了 加载操作(关联查询),即发第二条SQL
写在最后的话,使用延迟加载,只有多条sql的关联查询才可以可以,单条的不可以,因为单条做的是表连接,直接一张表一下子就出来数据了
缓存
很熟悉的一个词,什么是缓存?
好多人都不太能解释清楚缓存的概念,运用到缓存的地方大家都很清楚,像什么网站了,视频缓存啊,等等
我从百度百科copy一个缓存的概念,读一下,免得看完这篇博客都对缓存的概念一无所知
缓存就是数据交换的缓冲区(称作Cache),当某一硬件要读取数据时,会首先从缓存中查找需要的数据,如果找到了则直接执行,找不到的话则从内存中找。由于缓存的运行速度比内存快得多,故缓存的作用就是帮助硬件更快地运行。
有了一定概念了把,MyBatis中有些实现不同,不过意思相似,不然也不会叫做缓存
MyBatis中一级缓存(他是默认开启的)
在同一个SqlSession中,执行相同的查询SQL,第一次会去查询数据库,并写到缓存中;第二次直接从缓存中取。
MyBatis缓存里面实则是个hashmap,key值为hashcode+selectId+sql语句,value为查询返回结果的内存地址的引用(指针),
是为了更好的理解编程的灵魂,深入它的全部,才会有所成
mabatis中一级缓存的存在性证明 (存在的),增删改对一级缓存的影响(会清空一级缓存)-----》