Mybatis缓存
我们都知道,在进行频繁的数据库查询操作时,比较耗费资源。这时,缓存的重要性不言而喻。在第一次查询时,就将查询结果放入缓存,后续相同的查询操作,直接从缓存查找对应数据即可。Mybatis则提供了两级缓存机制。分别是一级缓存(作用于一个sqlsession会话,默认开启)和二级缓存(基于namespace级别的缓存,一个命名空间对应一个二级缓存)
一、一级缓存
一级缓存默认开启,它作用于一个sqlsession会话,也就是从建立sqlsession连接至——连接关闭。比如我两次通过同一个用户id查询用,代码和测试如下:
@Test
public void findUserById(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDAO userDAO = sqlSession.getMapper(UserDAO.class);
User user = userDAO.findUserById(1);
User user1 = userDAO.findUserById(1);
System.out.println(user == user1);
sqlSession.close();
}
在mybatis配置文件中已经使用默认日志STDOUT_LOGGING。结果如下
可以看出两次查询只对数据库做了一次查询,即第二次从缓存查得结果。下面我们进一步看一下一级缓存的失效情况。
缓存失效情况
根据mybatis官方文档,一级缓存只限于前后查询相同的数据,若前后查询过程中出现增删改操作,即使不是作用于查询对象,也会使得缓存被清除。以更新操作为例,代码如下:
@Test
public void findUserById(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDAO userDAO = sqlSession.getMapper(UserDAO.class);
User user = userDAO.findUserById(1);
userDAO.updateUser(new User(2,"xiao","1231"));
User user1 = userDAO.findUserById(1);
System.out.println(user == user1);
sqlSession.close();
}
在两次查询操作之间更新id为2的用户信息,结果如下:
可以看出,一共执行了3条SQL,即中间的更新操作将一级缓存刷新,导致第二次查询操作需要重新从数据库读取数据。
二、二级缓存
二级缓存也叫全局缓存,由于一级缓存作用域太低,从而诞生了二级缓存。它是基于namespace级别的缓存,一个命名空间对应一个二级缓存默认开启。下面进行测试
工作机制
- 一个会话查询一条数据,数据就被放入一级缓存
- 如果当前会话关闭,一级缓存中数据就被清除,但我们希望关闭时,将数据放入二级缓存。
- 新会话查询信息,就可以先从二级缓存中查找。
- 其中不同的mapper查询的数据会放在各自的缓存(map)中。
步骤
显示的在mybatis配置文件下的settings中进行配置,提高可读性
<setting name="cacheEnabled" value="true"/>
随后在*mapper.xml下增加标签,表示使用二级缓存。当然也能在select语句中使用useCache选项。
测试
新建两个会话(基于同一个mapper查询),查看第二个会话在第一个会话关闭后,能否从二级缓存中获得第一个会话查询的数据。
代码如下:
@Test
public void findUserById(){
SqlSession sqlSession1 = MybatisUtils.getSqlSession();
SqlSession sqlSession2 = MybatisUtils.getSqlSession();
UserDAO userDAO1 = sqlSession1.getMapper(UserDAO.class);
User user1 = userDAO1.findUserById(1);
sqlSession1.close();
UserDAO userDAO2 = sqlSession2.getMapper(UserDAO.class);
User user2 = userDAO2.findUserById(1);
System.out.println(user1 == user2);
sqlSession2.close();
}
测试结果如下:
可以看出,只执行一次SQL,即第二次已经通过二级缓存成功获取到数据。
缓存顺序
mybatis中数据查询策略
- 先查询二级缓存
- 再查询一级缓存
- 最后查询数据库
总结
合理使用二级缓存,降低数据库负担,在实际项目中也能提高系统响应速度。