本文已参与新人创作礼活动,一起开启掘金创造之路。
【Mybatis专栏】(五)Mybatis缓存
MyBatis 有两种缓存:⼀级缓存和⼆级缓存。
一级缓存
- 一级缓存默认打开,无需在xml中配置
- ⼀级缓存的数据存储在 SqlSession 中
- 如果 SqlSession 执⾏了增、删、改操作, MyBatis 会⾃动清空 SqlSession 缓存中的数据,以此来保证数据的⼀致性
public static void l1CacheTest() {
InputStream inputStream = Test.class.getClassLoader().getResourceAsStream("config.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
ClassesRepository classesRepository = sqlSession.getMapper(ClassesRepository.class);
Classes classes = classesRepository.lazyFindById(3); //1、第一次select
System.out.println(classes.getName());
classes = classesRepository.lazyFindById(3);//2、第二次select
System.out.println(classes.getName());
classes.setName("3班");
classesRepository.updateByInstance(classes);//3、update后再select
classes = classesRepository.lazyFindById(3);
System.out.println(classes.getName());
sqlSession.close();//close
sqlSession = sqlSessionFactory.openSession();
classesRepository = sqlSession.getMapper(ClassesRepository.class);
classes = classesRepository.lazyFindById(3);//4、close后再次select
System.out.println(classes.getName());
sqlSession.close();
}
疑问
在update之后,
没有提交事务,select出来的name是修改后的值,但是在close sql session后,再次select出来的是修改前的值。为什么?
没有提交事务,修改的数据最终就没有存到磁盘或者内存中去
sql session是跟MySQL通信的,而MySQL是跟数据存储单元(磁盘或内存)通信的
MySQL 5.5 版本以后,默认存储引擎为 InnoDB,而InnoDB存在Buffer Pool,是否与这个有关,等待后续学习再完善
二级缓存
- 二级缓存作用域大于一级缓存,作用于整个mapper
- MyBatis ⼆级缓存默认是关闭的,需要使⽤时可以通过配置⼿动开启
- MyBatis 可以使⽤⾃带的⼆级缓存,也可以使⽤第三⽅
ehcache⼆级缓存
二级缓存config.xml配置
<setting name="cacheEnabled" value="true"/>
自带二级缓存mapper.xml配置
<mapper namespace="org.sample.repository.MyClassRepository">
<cache/>
</mapper>
其实体类需要实现Serializable 接口
public class MyClass implements Serializable {
//Serializable 序列化接口
private Integer id;
private String name;
}
第三方二级缓存ehcache ehcache.xml配置
<ehcache xmlns:xsi="<http://www.w3.org/2001/XMLSchema-instance>" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
<diskStore/>
<defaultCache
maxElementsInMemory="1000"
maxElementsOnDisk="10000000"
eternal="false"
overflowToDisk="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
</defaultCache>
</ehcache>
第三方二级缓存ehcachemapper.xml配置
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "<http://mybatis.org/dtd/mybatis-3-mapper.dtd>">
<mapper namespace="org.sample.repository.EhcacheMyClassRepository">
<!-- 开启⼆级缓存 -->
<cache type="org.mybatis.caches.ehcache.EhcacheCache" >
<!-- 缓存创建以后,最后⼀次访问缓存的时间⾄失效的时间间隔 -->
<property name="timeToIdleSeconds" value="3600"/>
<!-- 缓存⾃创建时间起⾄失效的时间间隔-->
<property name="timeToLiveSeconds" value="3600"/>
<!-- 缓存回收策略, LRU移除近期最少使⽤的对象 -->
<property name="memoryStoreEvictionPolicy" value="LRU"/>
</cache>
</mapper>
第三方二级缓存的实体类不需要实现
Serializable接口
sql session close后重新open结果👇只访问了一次MySQL