Mybatis从入门到精通系列 12——Mybatis 的一级缓存与二级缓存
Posted Xiu Yan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mybatis从入门到精通系列 12——Mybatis 的一级缓存与二级缓存相关的知识,希望对你有一定的参考价值。
Mybatis 框架也有提供了缓存策略,通过缓存策略来减少数据库的查询次数,从而提高性能。Mybatis中缓存分为一级缓存,二级缓存。
一、问题题出
-
什么是缓存
存在于内存中的临时数据。 -
为什么使用缓存
减少和数据库的交互次数,提高执行效率。 -
什么样的数据能使用缓存,什么样的数据不能使用
适用于缓存: 经常查询并且不经常改变的。数据的正确与否对最终结果影响不大的。
不适用于缓存: ① 经常改变的数据; ②数据的正确与否对最终结果影响很大的。
例如:商品的库存,银行的汇率,股市的牌价。
二、Mybatis 的一级缓存
2.1 一级缓存概述
一级缓存:
它指的是 Mybatis中 SqlSession 对象的缓存。当我们执行查询之后,查询的结果会同时存入到 SqlSession 为我们提供一块区域中。该区域的结构是一个 Map。当我们再次查询同样的数据,Mybatis 会先去 Sqlsession 中查询是否有,有的话直接拿出来用。 当 SqlSession对象消失时,Mybatis的一级缓存也就消失了。
2.2 一级缓存实现
示例代码1:
@Test
public void testFirstLevelCache_1() {
User user1 = userDao.findById(41);
System.out.println(user1);
User user2 = userDao.findById(41);
System.out.println(user2);
System.out.println(user1==user2);//打印true
}
测试结果:
我们可以发现,虽然在上面的代码中我们查询了两次,但最后只执行了一次数据库操作,这就是 Mybatis 提供给我们的一级缓存在起作用了。因为一级缓存的存在,导致第二次查询 id 为 41 的记录时,并没有发出 sql 语句从数据库中查询数据,而是从一级缓存中查询。
示例代码2:
@Test
public void testFirstLevelCache_2() {
User user1 = userDao.findById(41);
System.out.println(user1);
// sqlSession.close();
// sqlSession = factory.openSession();
sqlSession.clearCache();//此方法也可以清空缓存
userDao = sqlSession.getMapper(IUserDao.class);
User user2 = userDao.findById(41);
System.out.println(user2);
System.out.println(user1==user2);
}
测试结果:
从以上测试结果我们发现,当清空缓存之后,Mybatis 会重新发出 sql 语句进行数据库的查询。
2.2 一级缓存注意事项
一级缓存是 SqlSession 范围的缓存,当调用SqISession 的修改,添加,删除,commit(), close()等方法时,就会清空一级缓存。
@Test
public void testClearCache(){
//1. 查询
User user1 = userDao.findById(41);
System.out.println(user1);
//2. 更新
user1.setUsername("update clear cache user");
user1.setAddress("河北省秦皇岛市");
userDao.updateUser(user1);
//3. 再次查询
User user2 = userDao.findById(41);
System.out.println(user2);
System.out.println(user1==user2);
}
测试结果:
三、Mybatis 的二级缓存
3.1 二级缓存概述
它指的是Mybatis中 SqlSessionFactory 对象的缓存。由同一个 SqlSessionFactory 对象创建的 SqlSession 共享其缓存。
3.2 二级缓存的开启与关闭
使用步骤:
第一步 : 让 Mybatis 框架支持二级缓存(在SqlMapConfig.xml中配置)
第二步 : 让当前的映射文件支持二级缓存(在IUserDao.xml中配置)
第三步 : 让当前的操作支持二级缓存(在select标签中配置)
-
第一步:主配置文件中支持二级缓存
<settings> <setting name="cacheEnabled" value="true"></setting> </settings>
因为 cacheEnabled 的取值默认就为 true,所以这一步可以省略不配置。为 true 代表开启二级缓存;为false 代表不开启二级缓存。
-
第二步:映射文件支持二级缓存
<!--开启user支持二级缓存--> <cache/>
-
第三步:让当前的操作支持二级缓存
<!--根据id查询用户,添加 useCache 属性,并指定为true--> <select id="findById" parameterType="INT" resultType="user" useCache="true"> select * from user where id = #{id} </select>
示例:
@Test
public void testFirstLevelCache(){
SqlSession sqlSession1 = factory.openSession();
IUserDao dao1 = sqlSession1.getMapper(IUserDao.class);
User user1 = dao1.findById(41);
System.out.println(user1);
sqlSession1.close();//一级缓存消失,
SqlSession sqlSession2 = factory.openSession();
IUserDao dao2 = sqlSession2.getMapper(IUserDao.class);
User user2 = dao2.findById(41);
System.out.println(user2);
sqlSession2.close();
//System.out.println(sqlSession1==sqlSession2);
System.out.println(user1 == user2);//false, 因为二级缓存存放的内容是数据,而不是对象。将第一次查询得到对象的数据保存到缓存中,第二次查询时,将数据封装到新的对象user2里面.
// 虽然是false,但是只发起了一次查询,证明二级缓存开启成功
}
测试结果:
本文针对 Mybatis 中一级缓存和二级缓存进行了总结归纳,如果大家对文章内容还存在一些疑问,欢迎大家在评论区留言哦~
以上是关于Mybatis从入门到精通系列 12——Mybatis 的一级缓存与二级缓存的主要内容,如果未能解决你的问题,请参考以下文章
Mybatis从入门到精通系列 12——Mybatis 的一级缓存与二级缓存
Mybatis从入门到精通系列 11——Mybatis 延迟加载与立即加载
Mybatis从入门到精通系列 09——Mybatis多表查询之一对多查询