Mybatis缓存
资料来自
一级缓存和二级缓存
一级缓存和二级缓存
注解
mapper
一级缓存
一级缓存,是指SqlSession级别的缓存。一级缓存是一直开启的,在操作数据库时需要构造sqlSession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据。不同的sqlSession之间的缓存数据区域(HashMap)是互相不影响的
public void TestCache01() throws IOException {
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
SqlSession openSession = sqlSessionFactory.openSession();
try {
EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
Employee emp01 = mapper.getEmpById(1);
System.out.println(emp01);
Employee emp02 =mapper.getEmpById(1);
System.out.println(emp02);
//从日志中可以看到sql查询只执行了一次,这就是mybatis的一级缓存
//第二次与第一次查询语句相同,第二次查询返回值直接使用第一次的结果
//从==判断地址也可以看出
System.out.println(emp01==emp02);
}finally {
openSession.close();
}
}
一级缓存失效
- sqlSession不同
- sqlSession相同,查询条件不同
- sqlSession相同,两次查询之间执行了增删改操作
- 如果SqlSession调用了close()方法
- 如果SqlSession调用了clearCache()
二级缓存
二级缓存,是指mapper级别的缓存,多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的,二级缓存默认是不开启的,因为需要配置
基本配置步骤
- 相关的
bean
需要序列化,为了将缓存数据取出执行反序列化操作,因为二级缓存数据存储介质多种多样,不一定只存在内存中,有可能存在硬盘中,如果我们要再取这个缓存的话,就需要反序列化了,所以mybatis中的pojo都去实现Serializable接口
public class Student implements Serializable {
private String id;
private String name;
private String age;
private String sex;
...
}
- Mybatis缓存配置
// mybatis-config.xml
<configuration>
<settings>
<!-- 开启二级缓存 -->
<setting name="cacheEnabled" value="true"/>
</settings>
...
</configuration>
- 注解模式使用
// CacheNamespace这个注解的参数可以自己查看
@CacheNamespace(blocking=true)
public interface UserMapper{
@Select("select * from t_user where user_id = #{userId}")
@Options(useCache = true) // 针对每次查询都需要最新的数据 sql,要设置成 useCache=false,禁用二级缓存
List<User> getUser(User u);
}
- mapper模式使用
<?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="cn.mybatis.UserMapper">
// eviction="FIFO" FIFO(先进先出),LRU(最近使用次数最少的 被优先清除),LFU(最近一段时间内使用次数最少)
// flushInterval="60000" 自动刷新时间60s
// size="512" 最多缓存512个引用对象
// readOnly="true 只读
// type 指定自己实现的cache的路径,默认PerpetualCache
<cache eviction="LRU" />
// 针对每次查询都需要最新的数据 sql,要设置成 useCache=false,禁用二级缓存
<select id="selectById" useCache="false">
select * from test where id = #{id}
</select >
</mapper>
上面的两个模式都是使用Mybatis默认的缓存类PerpetualCache
,但是这个缓存是单服务器工作,无法实现分布式缓存,流行的两个代替默认缓存的插件是,ehcache
和redis
如何看出有没有使用缓存
在日记打印区域里,没有执行sql就是调用的缓存