美文网首页java后端05 应用技术程序员
MyBatis(4)一级缓存,二级缓存

MyBatis(4)一级缓存,二级缓存

作者: RonaldoWang | 来源:发表于2017-03-05 17:39 被阅读109次

    MyBatis的缓存,包括一级缓存,二级缓存。

    什么是一级缓存?

    一级缓存指的就是sqlsession,在sqlsession中有一个数据区域,是map结构,这个区域就是一级缓存区域。一级缓存中的key是由sql语句、条件、statement等信息组成一个唯一值。一级缓存中的value,就是查询出的结果对象。

    什么是二级缓存?

    二级缓存指的就是同一个namespace下的mapper,二级缓存中,也有一个map结构,这个区域就是一级缓存区域。一级缓存中的key是由sql语句、条件、statement等信息组成一个唯一值。一级缓存中的value,就是查询出的结果对象。

    一级缓存是默认使用的。

    二级缓存需要手动开启。

    MyBatis缓存框架图

    MyBatis缓存框架图

    一级缓存原理图

    代码测试:

     /**
     * 测试一级缓存
     * @throws Exception
     */
    @Test
    public void testSelectStudentById() throws Exception {
        SqlSession session1 = sqlSessionFactory.openSession();
        // 拿到代理对象
        StudentMapper mapper = session1.getMapper(StudentMapper.class);
        //第一次查询id为1的Student的信息
        Student student1 = mapper.selectStudentById(1);
        System.out.println(student1);
        //第二次查询时,发现缓存中有id为1的Student的信息,于是从缓存中读取
        Student student2 = mapper.selectStudentById(1);
        System.out.println(student2);
        session1.close();
    }
    

    然后debug看一下

    再回头看一下上面一级缓存原理图中间那一部分,当修改删除更新时commit,会自动清空缓存

    代码测试:

     /**
     * 测试一级缓存
     * @throws Exception
     */
    @Test
    public void testSelectStudentById() throws Exception {
        SqlSession session1 = sqlSessionFactory.openSession();
        // 拿到代理对象
        StudentMapper mapper = session1.getMapper(StudentMapper.class);
        //第一次查询id为1的Student的信息
        Student student1 = mapper.selectStudentById(1);
        System.out.println(student1);
        //更新操作
        student1.setName("RonaldoWang");
        mapper.updateStudent(student1);
        //commit()就会清空缓存
        session1.commit();
        //第二次查询时,发现缓存中有id为1的Student的信息,于是从缓存中
        Student student2 = mapper.selectStudentById(1);
        System.out.println(student2);
        session1.close();
    }
    

    测试结果:


    二级缓存原理图

    看起来二级缓存与一级缓存相似,只是二级缓存的范围更广,区域划分是namespace,而一级缓存是在sqlsession里面。

    1.开启二级缓存

    第一步:总开关开启,需要在sqlMapConfig.xml中通过settings标签开启,默认它就是开启的,但还是写上去比较好,容易阅读吧。

    第二步:在Mapper.xml下namespace中开启自己的开关

    第三步:在PO类中实现序列化操作。

    )

    之所以需要实现序列化接口,是因为方便反序列化,二级缓存的区域不一定只是在内存中,也有可能在硬盘中。

    测试代码:

    /**
     * 测试二级缓存
     * @throws Exception
     */
    @Test
    public void testSelectStudentById() throws Exception {
        SqlSession session1 = sqlSessionFactory.openSession();
        SqlSession session2 = sqlSessionFactory.openSession();
        SqlSession session3 = sqlSessionFactory.openSession();
    
        StudentMapper mapper1 = session1.getMapper(StudentMapper.class);
        StudentMapper mapper2 = session2.getMapper(StudentMapper.class);
        StudentMapper mapper3 = session2.getMapper(StudentMapper.class);
        
        Student student1 = mapper1.selectStudentById(1);
        System.out.println(student1);
        //这里close很关键,在二级缓存中,close()会将数据放到二级缓存中
        session1.close();
        Student student3 = mapper3.selectStudentById(1);
        System.out.println(student3);
        session3.close();
    }
    

    测试结果:


    上面代码中session2,和mapper2还没有用到,这里可以用mapper2给数据更新一下,看看是否会将缓存清空?

    测试代码

    /**
     * 测试二级缓存
     * @throws Exception
     */
    @Test
    public void testSelectStudentById() throws Exception {
        SqlSession session1 = sqlSessionFactory.openSession();
        SqlSession session2 = sqlSessionFactory.openSession();
        SqlSession session3 = sqlSessionFactory.openSession();
    
        StudentMapper mapper1 = session1.getMapper(StudentMapper.class);
        StudentMapper mapper2 = session2.getMapper(StudentMapper.class);
        StudentMapper mapper3 = session3.getMapper(StudentMapper.class);
        
        Student student1 = mapper1.selectStudentById(1);
        System.out.println(student1);
        //这里close很关键,在二级缓存中,close()会将数据放到二级缓存中
        session1.close();
        
        
        Student student2 = mapper2.selectStudentById(1);
        student2.setName("小六子");
        mapper2.updateStudent(student2);
        session2.commit();
        session2.close();
        
        
        Student student3 = mapper3.selectStudentById(1);
        System.out.println(student3);
        session3.close();
    }
    

    测试结果:


    圈出来的看看就能理解了。

    禁用缓存

    )

    刷新缓存

    刷新缓存在select语句中默认是false

    相关文章

      网友评论

        本文标题:MyBatis(4)一级缓存,二级缓存

        本文链接:https://www.haomeiwen.com/subject/pzjegttx.html