Mybatis缓存,超详细!包含:懒加载、立即加载、缓存、一级缓存、二级缓存、自定义缓存

Mybatis缓存

延迟(懒)加载 和 立即加载

  • 延迟(懒)加载

    在真正使用数据时才发起查询,不用的时候不查询,按需加载(也叫 懒加载)

    ​ 比如:

    ​ 在查询班级信息,每个班级都会有很多的学生(假如每个班有100个学生),如果我 们只是查看班级信息,但是学生对象也会加载到内存中,会造成浪费。

    ​ 所以我门需要进行懒加载,当确实需要查看班级中的学生信息,我门在进行加载班级 中的学生信息

    通常: 一对多,或者多对多的是需要使用延迟加载

  • 立即加载

    不管用不用信息,只要调用,马上发起查询并进行加载

    ​ 当我们查询学生信息时,就需要知道学生在哪个班级中,所以就需要立马去查询班级 的信息

    通常:当 一对一或者 多对一的时候需要立即加载

案例:

例如现在对学生表进行查询

mapper.java

@Select("select * from student")
public List<Student> findStudentAndClass();

实现类:

List<Student> slist = stuMapper.findStudentAndClass();
Student s = slist.get(0);
System.out.println(s);

实现类中只需要集合中的第一个数据,应该只需要去查询该学生对应的班级,但它会把全部班级查出来,这就是立即加载。立即加载就是不管是否需要数据,只要一进行查询,就会把相关联的数据一并查询出来

懒加载只会去查询第一个数据对应的班级,用的时候才查询,不用的时候不查询

设置懒加载

在主配置文件中添加<settings>,该标签要在<properties>之下,<typeAliases>之上

<settings>
	<setting name="lazyLoadingEnabled" value="true"/>  
    <!-- 开启懒加载 -->
	<setting name="aggressiveLazyLoading" value="false"/>
   	<!-- 关闭层级加载 -->
</settings>

层级加载:层级加载是在开启懒加载之后才会有(3.4.1之前默认开启),它会在空闲时间把其他不用的加载到内存中,实现全部加载

开启懒加载后只会查询用的数据

动态sql中开启懒加载:fetchType属性

@Results({
			@Result(column = "classid", property = "classid"),
			@Result(property = "bj",column = "classid", 
				one = @One(select = "com.ape.mapper.BanjiMapper.findBanjiByClassid",fetchType = FetchType.LAZY) )
			
	})
	@Select("select * from student")
	public List<Student> findStudentAndClass();

fetchType属性的值是三个枚举值,赋值eg:fetchType = FetchType.LAZY(FetchType.)

  1. DEFAULT:主配置文件是什么加载默认就是什么加载
  2. EAGER:立即加载
  3. LAZY:懒加载,延迟加载

xml中在<association>中添加属性 fetchType=" "

<association property="" select="" fetchType="lazy" >
</association>

缓存

  • 缓存

    缓存(cache),数据交换的缓冲区,当应用程序需要读取数据时,先从数据库中将数据取出,放置在缓冲区中,应用程序从缓冲区读取数据

    特点:数据库取出的数据保存在内存中,具备快速读取和使用

    限制:读取时无需再从数据库获取,数据可能不是最新的

  • 命中和未命中

    1. 命中:需要的数据在缓存中找到结果

    2. 未命中:需要的数据在缓存中未找到结果

  • mybatis缓存的意义

    减少对数据库的访问,降低时间资源,提升效率

  • 缓存的适用性

    1. 适合使用缓存

      ​ 经常查询并且不经常改变的

      ​ 数据的正确与否对最终结果影响不大的

      ​ 比如:一个公司的介绍,新闻等

    2. 不适合适用缓存

      ​ 经常改变的数据

      ​ 数据的正确与否对最终结果影响很大

      ​ 比如商品的库存,股市的牌价等

一级缓存

  • 会话 session 级别的缓存,针对一次会话操作内

  • 默认开启,一级缓存只是相对同一个 SqlSession 对象而言。

例如:同一个sqlsession对象中,执行了两条相同的sql,第二次不会再去查询数据库,直接调用第一次查询缓存的数据

Mapper.java

@Select("select * from student where sid = #{v}")
public Student findStudentBySid(int sid);

实现类

SqlSession sqlSession = DaoUtil.getSqlSession();
StudentMapper stuMapper = sqlSession.getMapper(StudentMapper.class);
// 查询5号学生
Student s = stuMapper.findStudentBySid(5);
System.out.println(s);
// 业务逻辑...
for(int i = 0; i< 100; i++) {
	System.out.print(i);
}
// 再次查询5号学生
Student s2 = stuMapper.findStudentBySid(5);

第二次查询s2不会执行sql语句,直接返回缓存中的结果

输出System.out.print(s1 == s2); 为true,说明s2拿的是缓存中的数据

  • 一级缓存

在这里插入图片描述

一级缓存查询时,先找缓存cache,没有去查数据库,查询到结果先缓存,再返回给用户

工作流程

在这里插入图片描述
在这里插入图片描述

注意事项:一级缓存失效的情况

  1. 使用不同的sqlsession

  2. 同一个sqlsession单查询条件不同

  3. 同一个sqlsession两次查询期间执行了任何一次增删改,commit(),close()操作

  4. 同一个sqlsession两次查询期间手动清空了缓存

    sqlsession.clearCache();    // 清空缓存
    

二级加载(基本不用)

一级缓存最大的范围就是一个sqlsession,那么如果多个 SqlSession 需要共享缓存,此时就需要二级缓存

  • 二级缓存:Mapper 级别的,只要是同一个 Mapper,无论使用多少个 SqlSession 来操作,数据都是共享的,多个不同的 SqlSession 可以共用二级缓存,MyBatis 二级缓存默认是关闭的,需要使用时可手动开启,二级缓存也可以使用第三方的缓存,比如,使用 Ehcache 作为二级缓存

  • 二级缓存配置

    1. 主配置文件

      在这里插入图片描述

    2. 注解

      在这里插入图片描述

  • 二级缓存总结

    1. Mybatis 的二级缓存相对于一级缓存来说,实现了缓存数据的共享,可控性也更强
    2. 极大可能会出现错误数据,有设计上的缺陷,安全使用的条件比较苛刻
    3. 分布式环境下,必然会出现读取到错误数据,所以不推荐使用

自定义缓存

  • 自定义缓存分类

    1. 实现缓存接口

      实现 org. apache. ibatis. cache. Cache 接口自定义缓存

    2. 引入第三方缓存

      引入 Redis 等第三方内存库作为 MyBatis 缓存

一级缓存和二级缓存的区别

  1. 一级缓存是 SqlSession 级别的缓存,它的作用域是同一个 SqlSession,同一个SqlSession 中的多次查询会共享同一个缓存。二级缓存是 Mapper 级别的缓存,它的作用域是同一个 Mapper,同一个 Mapper 中的多次查询会共享同一个缓存
  2. 一级缓存是默认开启的,不需要手动配置。二级缓存需要手动配置,需要在 Mapper.xml 文件中添加 标签
  3. 一级缓存的生命周期是和 SqlSession 一样长的,当 SqlSession 关闭时,一级缓存也会被清空。二级缓存的生命周期是和 MapperFactory 一样长的,当应用程序关闭时,二级缓存也会被清空
  4. 一级缓存只能用于同一个 SqlSession 中的多次查询,不能用于跨 SqlSession 的查询。二级缓存可以用于跨 SqlSession 的查询,多个 SqlSession 可以共享同一个二级缓存
  5. 一级缓存是线程私有的,不同的 SqlSession 之间的缓存数据不会互相干扰。二级缓存是线程共享的,多个 SqlSession 可以共享同一个二级缓存,需要考虑线程安全问题
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CodeMonkey-D

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值