下图是多个sqlSession请求UserMapper的二级缓存图解。二级缓存是mapper级别的。
第一次调用mapper下的SQL去查询用户信息。查询到的信息会存到该mapper对应的二级缓存区域内。
第二次调用相同namespace下的mapper映射文件中相同的SQL去查询用户信息。会去对应的二级缓存内取结果。
如果调用相同namespace下的mapper映射文件中的增删改SQL,并执行了commit操作。此时会清空该namespace下的二级缓存。
1开启二级缓存
Mybatis默认是没有开启二级缓存
在全局sqlMapConfig中添加 setting标签, 开启二级缓存总开关
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
在对应的UserMapper.xml映射文件中,开启二级缓存
<mapper namespace="cn.itcast.mapper.UserMapper">
<!-- 开启二级缓存, 默认使用PerpetualCache -->
<cache type="org.apache.ibatis.cache.impl.PerpetualCache"></cache>
2实现序列化
由于二级缓存的数据不一定都是存储到内存中,它的存储介质多种多样,所以需要给缓存的对象执行序列化。
如果该类存在父类,那么父类也要实现序列化。
public class User implements Serializable{
3测试
测试1:两个不同的sqlsession根据用户id=1查询用户 一次数据库
@Test
public void testTwoLevelCache() throws Exception{
SqlSession sqlSession1 = sqlSessionFactory.openSession();
SqlSession sqlSession2 = sqlSessionFactory.openSession();
SqlSession sqlSession3 = sqlSessionFactory.openSession();
UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);
UserMapper userMapper3 = sqlSession3.getMapper(UserMapper.class);
//第一次查询
User user1 = userMapper1.findUserById(1);
System.out.println(user1);
sqlSession1.close();
// userMapper3.insertUser(user1);
// sqlSession3.commit();
//第二次查询
User user2 = userMapper2.findUserById(1);
System.out.println(user2);
sqlSession2.close();
sqlSession3.close();
}
测试2:在两次查询中间,插入用户,并执行commit 2次数据库
@Test
public void testTwoLevelCache() throws Exception{
SqlSession sqlSession1 = sqlSessionFactory.openSession();
SqlSession sqlSession2 = sqlSessionFactory.openSession();
SqlSession sqlSession3 = sqlSessionFactory.openSession();
UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);
UserMapper userMapper3 = sqlSession3.getMapper(UserMapper.class);
//第一次查询
User user1 = userMapper1.findUserById(1);
System.out.println(user1);
sqlSession1.close();
//在close时候,才会将数据写入二级缓存
userMapper3.insertUser(user1);
sqlSession3.commit();
//第二次查询
User user2 = userMapper2.findUserById(1);
System.out.println(user2);
sqlSession2.close();
sqlSession3.close();
}