对于经常查询且不经常改变的数据,使用缓存可以减少数据库的交互次数,减少系统开销,提高效率
MyBatis可以定制和配置缓存,默认情况下自动开启了一级缓存(本地缓存),我们关闭不了
一级缓存是sqlSession级别的缓存,每个sqlSession中的缓存相互独立
我们在一次会话中执行两次查询,第一次查出的数据都会被默认放在前会话的一级缓存中,第二次查询要获取相同的数据,就直接从缓存中拿,而没有进行数据库查询,所以SQL语句只查询了一次
@Test
public void testQueryBlogIf(){
SqlSession session = MybatisUtils.getSession();
BlogMapper mapper = session.getMapper(BlogMapper.class);
HashMap<String, String> map = new HashMap<String, String>();
map.put("title","Spring揭秘");
map.put("author","张三");
List<Blog> blogs = mapper.queryBlogIf(map);
System.out.println(blogs);
List<Blog> blogs2 = mapper.queryBlogIf(map);
System.out.println(blogs2);
System.out.println(blogs == blogs2);
session.close();
}
没有使用到当前一级缓存的情况:
sqlSession不同
@Test
public void testQueryBlogIf(){
SqlSession session = MybatisUtils.getSession();
SqlSession session2 = MybatisUtils.getSession();
BlogMapper mapper = session.getMapper(BlogMapper.class);
BlogMapper mapper2 = session2.getMapper(BlogMapper.class);
HashMap<String, String> map = new HashMap<String, String>();
map.put("title","Spring揭秘");
map.put("author","张三");
List<Blog> blogs = mapper.queryBlogIf(map);
System.out.println(blogs);
List<Blog> blogs2 = mapper2.queryBlogIf(map);
System.out.println(blogs2);
System.out.println(blogs == blogs2);
session.close();
session2.close();
}
查询获取的数据不同
@Test
public void testQueryBlogIf(){
SqlSession session = MybatisUtils.getSession();
BlogMapper mapper = session.getMapper(BlogMapper.class);
BlogMapper mapper2 = session.getMapper(BlogMapper.class);
HashMap<String, String> map = new HashMap<String, String>();
map.put("title","Spring揭秘");
map.put("author","张三");
List<Blog> blogs = mapper.queryBlogIf(map);
System.out.println(blogs);
HashMap<String, String> map2 = new HashMap<String, String>();
map.put("title","Java编程思想");
map.put("author","李四");
List<Blog> blogs2 = mapper2.queryBlogIf(map2);
System.out.println(blogs == blogs2);
session.close();
}
两次查询之间执行了增删改操作
@Test
public void testQueryBlogIf(){
SqlSession session = MybatisUtils.getSession();
BlogMapper mapper = session.getMapper(BlogMapper.class);
HashMap<String, String> map = new HashMap<String, String>();
map.put("title","Spring揭秘");
map.put("author","张三");
List<Blog> blogs = mapper.queryBlogIf(map);
System.out.println(blogs);
HashMap<String, String> map2 = new HashMap<String, String>();
map2.put("title","Java8实战");
map2.put("author","王五");
map2.put("id","1");
mapper.updateBlog(map2);
List<Blog> blogs2 = mapper.queryBlogIf(map);
System.out.println(blogs2);
System.out.println(blogs == blogs2);
session.close();
}
手动清除了一级缓存
@Test
public void testQueryBlogIf(){
SqlSession session = MybatisUtils.getSession();
BlogMapper mapper = session.getMapper(BlogMapper.class);
HashMap<String, String> map = new HashMap<String, String>();
map.put("title","Spring揭秘");
map.put("author","张三");
List<Blog> blogs = mapper.queryBlogIf(map);
System.out.println(blogs);
session.clearCache();
List<Blog> blogs2 = mapper.queryBlogIf(map);
System.out.println(blogs2);
System.out.println(blogs == blogs2);
session.close();
}
会话提交或者关闭以后,这个会话对应的一级缓存就没了,我们可以让一级缓存中的数据转到二级缓存(叫全局缓存),新的会话查询就可以从二级缓存中获取数据了。二级缓存是基于namespace级别的缓存,可以通过实现Cache接口来自定义二级缓存
先去MyBatis核心配置文件中开启全局缓存
<setting name="cacheEnabled" value="true"/>
然后在每个mapper.xml中配置使用二级缓存
<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
测试
@Test
public void testQueryBlogIf(){
SqlSession session = MybatisUtils.getSession();
SqlSession session2 = MybatisUtils.getSession();
BlogMapper mapper = session.getMapper(BlogMapper.class);
BlogMapper mapper2 = session2.getMapper(BlogMapper.class);
HashMap<String, String> map = new HashMap<String, String>();
map.put("title","Spring揭秘");
map.put("author","张三");
List<Blog> blogs = mapper.queryBlogIf(map);
System.out.println(blogs);
session.close();
List<Blog> blogs2 = mapper2.queryBlogIf(map);
System.out.println(blogs2);
System.out.println(blogs == blogs2);
session2.close();
}
不同的mapper查出的数据会放在自己对应的缓存(map)中
只要开启了二级缓存,我们在同一个Mapper中的查询,就可以在二级缓存中拿到数据,查出的数据都会被默认先放在一级缓存中
只有会话提交或者关闭以后,一级缓存中的数据才会转到二级缓存中