MyBatis 存在 一级 和 二级 缓存(默认一级缓存是开启的)
一级缓存保存在 每个 SqlSession 中 互不影响。
二级缓存保存在 于Mapper(namespace ) 中。
缓存数据什么周期:
在一级缓存存在于单次的事务,创建SQLSession 到 SQLSession.close缓存被销毁,中间如果执行Commit命令,缓存同样会被清空。
一级缓存单次事务
- 第一次: SqlSession.findUserById(1) 缓存(空) 查询数据库
- 第二次: SqlSession.findUserById(1) 缓存(有) 读取 缓存
- 修改数据: SqlSession.commit() 缓存(自动清空) 数据被修改
- 第三次: SqlSession.findUserById(1) 缓存(空) 查询数据库
- 完成退出 SqlSession.close() 缓存(清空)
二级缓存
二级缓存 的域:使用 namespace 做为key,如果两个mapper 使用同一 namespace做key 那么就会共用一个 二级缓存
二级缓存 开启条件,
1、需要在 mapper.xml 中添加 <cache/>
标签。
2、被缓存的对象需要实现序列号接口,否者会报错。
测试:
public void selectOrder() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sqlSessionFactory.openSession();
OrderDaoLazy mapper = session.getMapper(OrderDaoLazy.class);
User user = mapper.findUser(1);
System.out.println(user.toString());
session.close();//关闭后,一级缓存就会被销毁,但是在同一namespace下,会保存在二级缓存内。
System.out.println("====================");
SqlSession session1 = sqlSessionFactory.openSession();
OrderDaoLazy mapper1 = session1.getMapper(OrderDaoLazy.class);
User user1 = mapper1.findUser(1);
System.out.println(user1.toString());
session.close();
}
<cache/>
中有一个参数
<cache
eviction="FIFO" //
flushInterval="60000" //每隔 60 秒刷新
size="512" //存数结果对象或列表的 512 个引用
readOnly="true"/>//返回的对象设置为只读,在不同线程中的调用者之间修改它们会导致冲突
具体可参见文档 :(http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html) 跳入页面 按 Ctrl+F 查找 flushInterval 可直接定位到。