开篇
mybatis缓存特点和hibernate缓存特点是及其相像,本篇博客通过实践简单的了解一下mybatis的一级二级缓存。
一级
特点:
一级缓存默认开启
生命周期同sqlsession
sqlsession间缓存不共享
sqlsession关闭或执行sqlsession.commit() 时一级缓存清空
二级
概念说明:和hibernate不同,mybatis的二级缓存不是以sqlsessionfactory为单位的,而是以mapper.xml中的namespace为单位划分的,也就是两个mapper的namespace如果相同他们使用的就是同一个二级缓存。
特点:
默认不开启,需手工配置
可多个sqlsession共享
如果某个session执行commit(),则该mappe下的二级缓存数据清空
二级缓存实例
一、开启二级缓存
1、全局配置文件,settings中添加
<setting name="cacheEnabled" value="true"/> |
2、在mapper.xml中开启,因为二级缓存是以mapper为单位的,所以要在具体的mapper.xml中开启
<!-- 开启本mapper的namespace下的二缓存 --> <cache/> |
配置原理:mybatis提供了一个cache接口,并且自身提供了一套实现,在mapper.xml中添加<cache/>的配置默认使用的是mybatis自身的缓存实现,如下图:
如果要在mybatis中使用其他的第三方缓存比如ehcache,只需要在mapper中修改该配置即可。
<!-- 开启本mapper的namespace下的二缓存 type:指定cache接口的实现类的类型,mybatis默认使用PerpetualCache 要和ehcache整合,需要配置type为ehcache实现cache接口的类型 --> <cache type="org.mybatis.caches.ehcache.EhcacheCache"/> |
二、序列化被缓存的pojo类,因为二级缓存数据的存储介质不定。当取出二级缓存时执行反序列化操作。
三、测试
1、多个sqlsession共享
测试代码:
// 二级缓存测试 @Test public void testCache2() throws Exception { SqlSession sqlSession1 = sqlSessionFactory.openSession(); SqlSession sqlSession2 = sqlSessionFactory.openSession();
// 创建代理对象 UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class); // 第一次发起请求,查询id为1的用户 User user1 = userMapper1.findUserById(1); System.out.println(user1);
//这里执行关闭操作,将sqlsession中的数据写到二级缓存区域 sqlSession1.close();
UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class); // 第二次发起请求,查询id为1的用户 User user2 = userMapper2.findUserById(1); System.out.println(user2); sqlSession2.close();
} |
跟踪结果:第一个请求发出了sql语句,缓存命中率0.0。第二次请求没有发出sql,缓存命中率0.5(表示一共发出两次请求,一次使用来缓存)。
2、mapper中的某个sqlsession执行commit(),二级缓存清空
测试代码:
// 二级缓存测试 @Test public void testCache2() throws Exception { SqlSession sqlSession1 = sqlSessionFactory.openSession(); SqlSession sqlSession2 = sqlSessionFactory.openSession(); SqlSession sqlSession3 = sqlSessionFactory.openSession();
// 创建代理对象 UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class); // 第一次发起请求,查询id为1的用户 User user1 = userMapper1.findUserById(1); System.out.println(user1); //这里执行关闭操作,将sqlsession中的数据写到二级缓存区域 sqlSession1.close();
//使用sqlSession3执行commit()操作 UserMapper userMapper3 = sqlSession3.getMapper(UserMapper.class); User user = userMapper3.findUserById(1); user.setUsername("张明明"); userMapper3.updateUser(user); //执行提交,清空UserMapper下边的二级缓存 sqlSession3.commit(); sqlSession3.close();
UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class); // 第二次发起请求,查询id为1的用户 User user2 = userMapper2.findUserById(1); System.out.println(user2); sqlSession2.close();
} |
跟踪结果:userMapper1第一次查询发出sql,userMapper3查询时没有发出sql,修改提交后,userMapper2查询时再次发出sql。
其他介绍
1、开启二级缓存时在mapper.xml中进行了配置,这样该mapper下的所有查询都开启了缓存,但是对更新频率较高数据的查询没有必要开启缓存,可以在对应的statement中使用useCache="false",这样针对该条sql的缓存就会关闭。