看了他,妈妈再也不用担心我被问到Mybatis缓存了

Mybatis缓存

一、一级缓存
1. 概念
  • sqlsession级别的缓存,即缓存的是SQL语句
  • 同一个sqlsession中执行多次查询条件相同的SQL,mybatis会提供一级缓存进行优化
2. 开启和关闭
  • 开启

    • 默认开启
  • 关闭

    <setting name="localCacheScope" value="STATEMENT"/>

3. 使用
@Test
    public void method() throws IOException {
        // 1.读取核心配置文件
        InputStream in = Resources.getResourceAsStream("mybatis-config.xml");

        // 2.获取sqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);


        // 3.获取sqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();

        // 4.获取mapper
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);

        // 5.调用相应的方法
        Student student = mapper.getStudentById(1);
        System.out.println(student);



        System.out.println("----------------------------");

        // 同一个sqlsession中执行相同的SQL查询,会走一级缓存
        Student student1 = mapper.getStudentById(1);
        System.out.println(student1);



        // 6.释放资源
        sqlSession.close();
        in.close();
    }
4. 什么时候失效
  • 通过同一个SqlSession执行更新操作时,这个更新操作不仅仅指代update操作,还指插入和删除操作;
  • 事务提交时会删除一级缓存;
  • 事务回滚时也会删除一级缓存
5. 使用建议
平时使用MyBatis时都是和Spring结合使用的,在整个Spring容器中一般只有一个SqlSession实现类(bean默认是单例的)。而Spring一般都是主动提交事务的,所以说一级缓存经常失效。

还有就是我们也很少在一个事务范围内执行同一个SQL两遍,上面的这些原因导致我们在开发过程中很少注意到MyBatis一级缓存的存在。

不怎么用并不是说不用,作为一个合格的开发者需要对这些心知肚明,要清楚的知道MyBatis一级缓存的工作流程。

二、二级缓存
1. 概念
  • mapper级别的缓存
2. 开启
  • 核心配置文件:mybtis-config.xml

     <setting name="cacheEnabled" value="true"/>
    
  • mapper

    @CacheNamespace(blocking = true)
    
3. 使用

/**
     * 二级缓存:
     *  1.同一个sqlsession中,相同的SQL查询,会走缓存
     *  2.中途执行了更新,则下次的SQL查询不走缓存
     *  3.前面的sqlsession关闭之后,后面的sqlsession如果执行的是相同的SQL,则会走缓存
     *
     * @throws IOException
     */
    @Test
    public void method2() throws IOException {
        // 1.读取核心配置文件
        InputStream in = Resources.getResourceAsStream("mybatis-config.xml");

        // 2.获取sqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);


        // 3.获取sqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();

        // 4.获取mapper
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);

        // 5.调用相应的方法
        Student student = mapper.getStudentById(1);
        System.out.println(student);


        System.out.println("----------------------------");

        // 执行更新操作:查看下面的查询是否还会走缓存
//        int num = mapper.updateById(1);
//        System.out.println(" num = "+num);
//
//        System.out.println("----------------------------");

        sqlSession.close();

        // 同一个sqlsession中执行相同的SQL查询,会走一级缓存
        SqlSession sqlSession1 = sqlSessionFactory.openSession();

        // 4.获取mapper
        StudentMapper mapper1 = sqlSession1.getMapper(StudentMapper.class);
        Student student1 = mapper1.getStudentById(1);
        System.out.println(student1);



        // 6.释放资源
        sqlSession1.close();
//        sqlSession.close();
        in.close();
    }
4. 什么时候失效
  • 二级缓存是以namespace(Mapper)为单位的,不同namespace下的操作互不影响。
  • insert,update,delete操作会清空所在namespace下的全部缓存。
  • 多表操作一定不要使用二级缓存,因为多表操作进行更新操作,一定会产生脏数据。
5. 使用建议
MyBatis的二级缓存实用性不是很大。一个原因就是Spring环境下,一本只有一个SqlSession,不存在sqlSession之间共享缓存;还有就是
MyBatis的缓存都不能做到分布式,所以对于MyBatis的二级缓存以了解为主。
总结
1. 一级缓存
一级缓存的本质是Executor的一个类似Map的属性;
一级缓存默认开启,将flushCache设置成true或者将全局配置localCacheScope设置成Statement可以关闭一级缓存;
在一级缓存开启的情况下,查询操作会先查询一级缓存,再查询数据库;
增删改操作和事务提交回滚操作会导致一级缓存失效;
由于Spring中事务是自动提交的,因此Spring下的MyBatis一级缓存经常失效。(但是并不表示不生效,除非你手动关闭一级缓存)
不能实现分布式。

2. 二级缓存
namesapce级别的缓存(Mapper级别或者叫做表级别的缓存),设计的主要目的是实现sqlSession之间的缓存共享;
开启二级缓存后,查询的逻辑是二级缓存->一级缓存->数据库;
insert,update,delete操作会清空所在namespace下的全部缓存;
多表查询一定不要使用二级缓存,因为多表操作进行更新操作,可能会产生脏数据。
总体来说,MyBatis的缓存功能比较鸡肋。想要使用缓存的话还是建议使用spring-cache等框架。

原文地址:https://www.cnblogs.com/pretttyboy/p/13288787.html