一级缓存
* MyBatis的一级缓存:
* MyBatis的一级缓存是SqlSession级别的,即通过同一个SqlSession查询的数据会被缓存
* 再次使用同一个SqlSession查询同一条数据,会从缓存中获取
* 使一级缓存失效的四种情况:
* 1) 不同的SqlSession对应不同的一级缓存
* 2) 同一个SqlSession但是查询条件不同
* 3) 同一个SqlSession两次查询期间执行了任何一次增删改操作,任意增删改会清空缓存
* 4) 同一个SqlSession两次查询期间手动清空了缓存
二级缓存
* MyBatis的二级缓存:
* MyBatis的二级缓存是SqlSessionFactory级别的,即通过同一个SqlSessionFactory所获取的SqlSession对象
* 查询的数据会被缓存,在通过同一个SqlSessionFactory所获取的SqlSession查询相同的数据会从缓存中获取
* MyBatis二级缓存开启的条件:
* a>在核心配置文件中,设置全局配置属性cacheEnabled="true",默认为true,不需要设置
* b>在映射文件中设置标签<cache/>
* c>二级缓存必须在SqlSession关闭或提交之后有效
* d>查询的数据所转换的实体类类型必须实现序列化的接口
* 使二级缓存失效的情况:
* 两次查询之间执行了任意的增删改,会使一级和二级缓存同时失效
代码示例
测试
此处测试缓存代码是基于一个搭建好的MyBatis项目的测试代码
如何观测到是否有一级或二级缓存,这里我们可以看运行测试方法后,执行了几次SQL语句,有缓存的情况下只有一条SQL语句的执行
一级
SqlSession sqlSession1 = SqlSessionUtil.getSqlSession();
UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
User userById1 = mapper1.getUserById(1);
System.out.println(userById1);
// 手动清空一级缓存
// sqlSession1.clearCache();
User userById2 = mapper1.getUserById(1);
System.out.println(userById2);
结果:
有缓存
清除缓存后
二级
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession1 = sqlSessionFactory.openSession(true);
SqlSession sqlSession2 = sqlSessionFactory.openSession(true);
UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
User userById1 = mapper1.getUserById(3);
System.out.println(userById1);
// sqlSession操作完毕后(关闭或提交),才会保存在二级缓存
sqlSession1.close();
UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
User userById2 = mapper2.getUserById(3);
System.out.println(userById2);
sqlSession2.close();
二级缓存需要在Mapper.xml映射文件开启配置
eviction
淘汰策略,LRU、FIFOsize
缓存个数flushInterval
刷新频率,即缓存过期时间
<cache eviction="LRU" flushInterval="60000" size="1000"/>
结果
有缓存
缓存失效(未执行sqlSession.close()
)
总结
此处只是简单了解MyBatis的一、二级缓存,感兴趣的伙伴可以参考其他博客深入学习。