Mybatis从入门到精通系列 12 —— Mybatis 的一级缓存与二级缓存

  Mybatis 框架也有提供了缓存策略,通过缓存策略来减少数据库的查询次数,从而提高性能。Mybatis中缓存分为一级缓存,二级缓存。

在这里插入图片描述



一、问题题出

  1. 什么是缓存
    存在于内存中的临时数据。

  2. 为什么使用缓存
    减少和数据库的交互次数,提高执行效率。

  3. 什么样的数据能使用缓存,什么样的数据不能使用

    适用于缓存: 经常查询并且不经常改变的。数据的正确与否对最终结果影响不大的。
    不适用于缓存: ① 经常改变的数据; ②数据的正确与否对最终结果影响很大的。
      例如:商品的库存,银行的汇率,股市的牌价。


二、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标签中配置)

  1. 第一步:主配置文件中支持二级缓存

    <settings>
    	<setting name="cacheEnabled" value="true"></setting>
    </settings>
    

    因为 cacheEnabled 的取值默认就为 true,所以这一步可以省略不配置。为 true 代表开启二级缓存;为false 代表不开启二级缓存。

  2. 第二步:映射文件支持二级缓存

    <!--开启user支持二级缓存-->
    <cache/>
    
  3. 第三步:让当前的操作支持二级缓存

    <!--根据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,但是只发起了一次查询,证明二级缓存开启成功
}

理解:二级缓存将查询到的 id 为 41 的用户数据,放入二级缓存。再次查询时,将数据填充到 new 的对象中去。

测试结果:
在这里插入图片描述


四、补充:注解配置开启二级缓存

基于注解配置开启二级缓存,第二步与基于XML配置有所区别,其需要在持久层接口名的上方添加@CacheNamespace(blocking = true)

实例:

@CacheNamespace(blocking = true)
public interface IUserDao {

	/**
     * 根据id查询用户
     */
    @Select("select * from user where id = #{uid}")
    User findById(Integer id);
}

测试方法:

 @Test
 public void testFindById(){
     SqlSession session1 = factory.openSession();
     IUserDao userDao1 = session1.getMapper(IUserDao.class);
     User user1 = userDao1.findById(41);
     System.out.println(user1);

     session1.close();//一级缓存消失

     SqlSession session2 = factory.openSession();
     IUserDao userDao2 = session2.getMapper(IUserDao.class);
     User user2 = userDao2.findById(41);
     System.out.println(user2);

     session2.close();

     System.out.println(user1==user2);
 }

测试结果:在这里插入图片描述
打印false,但是只发起了一次查询,证明二级缓存开启成功。


本文针对 Mybatis 中一级缓存和二级缓存进行了总结归纳,如果大家对文章内容还存在一些疑问,欢迎大家在评论区留言哦~

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Xiu Yan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值