架构师养成记-mybatis一级缓存,二级缓存

一级缓存
级缓存是 MyBatis 中的默认提供的缓存的,也就是说,我们在使用 ybatis 的时候本身就在使用,他是默认开启的,级缓存是 sqlsession 级别的缓存,只有在一个 salSession 内的查询才能共享缓存的数据,当我们关闭 sqlsession 的时候或者执行增删改查的操作的时候,缓存就会被清空

 验证一级缓存

 @Test
    public void testCacheOne() throws Exception {
        InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory builder = new SqlSessionFactoryBuilder().build(inputStream);
        // 第一次获取sqlsession对象
        SqlSession sqlSession = builder.openSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        System.out.println("第一次查询....");
        User user = mapper.selectUserById(1);
        System.out.println(user);
        // 修改数据
//        user.setName("哈哈");
//        user.setAge(12);
//        int i = mapper.updateUserByUserId(user);
//        sqlSession.commit();


        // 第二次查询
        System.out.println("第二次查询....");
        UserMapper mapper1 = sqlSession.getMapper(UserMapper.class);
        User user1 = mapper1.selectUserById(1);
        System.out.println(user1);
        sqlSession.close();
    }
结果
第一次查询....
==>  Preparing: select * from t_user where id=?; 
==> Parameters: 1(Integer)
<==    Columns: id, name, age
<==        Row: 1, 嘿嘿, 21
<==      Total: 1
User(id=1, name=嘿嘿, age=21)
第二次查询....
User(id=1, name=嘿嘿, age=21)

这就说明在第二次查询的时候,并没有去数据库查询而是去缓存中拿了
我们看到在第一次查询的时候,发送了 sq1 去数据库中去查询,在第二次查询的时候没有发送任何 sq1 ,并且返回了同样的结果

在执行更新操作前 ,会先清空一级缓存,所以到这里我们就能才到,在第二次执行的时候,缓存中已经没有数据了,所以会在此执行和第一次一样的逻辑,继续从数据库中查找,所以在控制台我们看到会再一次的发送 sq1 语句。其他的删除、新增等操作对对缓存的影响,也是同样的逻辑(因为新增和删除底层都是执行的 update() 方法),大家可以试着自己去看下
所以,这里第二查询其实和第一查询是一致的。这里就不在源码分析了

 

MyBatis二级缓存
前面介绍了一级缓存,了解它的是 sqlsession 级别的缓存,是默认开启的,我们在使用 MyBatis 的时候其实就在使用,只是如果我们不去关注 sq1 可能不会注意到它;这篇文章我们就来了解一下另一个MyBatis 内提供的缓存-二级缓存,与一级缓存不同的二级缓存是 mapper( namespace) 级别的缓存,也就是说多个 sqlsession 对同一个Mapper进行查询操作时是可以共享这个 namespace 中的缓存数据,但是当我们去当前这个 mapper 中的进行增、、改或者 commit 的时候,同样是会清空缓存的

 从图中我们可以看出来,sqlsession1 在去查询数据的时候都会先去二级缓存中去查,如果没有的话在去数据库中查询,同时会存入到二级缓存中,等 sqlsession2 再去查询的时候,就可以直接从个缓存中拿了,但是 slsession3 去查询之前 sq1session2 去修改了查询的这个数据,那么就会二级缓存就会被清空;这样才不会出现脏数据的情况。

MyBatis的二级缓存是需要手动开启的,这里需要两步配置
1.在核心配置文件中 (mybatis-config.xml )

<settings>
    <!--全局缓存开关,默认开启-->
    <setting name="cacheEnabled " value="true"/>
  </settings>

2.映射文件中 ( UserMapper.xm1 )
<!--开启二级缓存-->
<cache/>
测试代码
/**
   * 使用二级缓存实体类要实现序列化接口
   *
   * @throws Exception
   */
  @Test
  public void testCache2() throws Exception {
    InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
    SqlSessionFactory build = new SqlSessionFactoryBuilder().build(inputStream);
    SqlSession sqlSession = build.openSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    System.out.println("===============第一次查询===================");
    User user = mapper.selectUserById(1);
    sqlSession.close();
    System.out.println(user);
    // 第二次查询
    System.out.println("===============第二次查询===================");
    SqlSession sqlSession2 = build.openSession();
    UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
    User user2 = mapper2.selectUserById(1);
    System.out.println(user2);

    System.out.println("===============更新数据===================");
//        user.setName("嘿嘿");
//        user.setAge(21);
//        mapper2.updateUserByUserId(user);
//        sqlSession2.commit();
//        sqlSession2.close();
    // 第三次查询
    System.out.println("===============第三次查询==================");
    SqlSession sqlSession3 = build.openSession();
    UserMapper mapper1 = sqlSession3.getMapper(UserMapper.class);
    User user1 = mapper1.selectUserById(1);
    System.out.println(user1);
    sqlSession3.close();
  }
结果
posted @ 2023-10-09 13:32  一滴水滴  阅读(21)  评论(0)    收藏  举报