• MyBatis 一级缓存实现详解及使用注意事项


    一级缓存介绍

    在应用运行过程中,我们有可能在一次数据库会话中,执行多次查询条件完全相同的SQL,MyBatis提供了一级缓存的方案优化这部分场景,如果是相同的SQL语句,会优先命中一级缓存,避免直接对数据库进行查询,提高性能。具体执行过程如下图所示。

    img

    每个SqlSession回话中会创建Executor执行器,每个Executor执行器中有一个Local Cache。当用户发起查询时,MyBatis根据当前执行的语句生成MappedStatement,在Local Cache进行查询,如果缓存命中的话,直接返回结果给用户,如果缓存没有命中的话,查询数据库,结果写入Local Cache,最后返回结果给用户。

    一级缓存配置

    我们来看看如何使用MyBatis一级缓存。开发者只需在MyBatis的配置文件中,添加如下语句,就可以使用一级缓存。共有两个选项,SESSION或者STATEMENT,默认是SESSION级别,即在一个MyBatis会话中执行的所有语句,都会共享这一个缓存。一种是STATEMENT级别,可以理解为缓存只对当前执行的这一个Statement有效。

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

    一级缓存实验

    开启一级缓存,范围为会话级别,调用三次getStudentById,代码如下所示:

    public void getStudentById() throws Exception {
        SqlSession sqlSession = factory.openSession(true); // 自动提交事务
        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
        System.out.println(studentMapper.getStudentById(1)); // 查询数据库
        System.out.println(studentMapper.getStudentById(1)); // 查询缓存
        System.out.println(studentMapper.getStudentById(1)); // 查询缓存
    }
    
    public void addStudent() throws Exception {
        SqlSession sqlSession = factory.openSession(true); // 自动提交事务
        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
        System.out.println(studentMapper.getStudentById(1)); // 查询数据库
        System.out.println(studentMapper.addStudent(buildStudent())); // 更新数据
        System.out.println(studentMapper.getStudentById(1)); // 查询数据库
        sqlSession.close();
    }
    
    public void testLocalCacheScope() throws Exception {
        SqlSession sqlSession1 = factory.openSession(true); 
        SqlSession sqlSession2 = factory.openSession(true); 
    
        StudentMapper studentMapper = sqlSession1.getMapper(StudentMapper.class);
        StudentMapper studentMapper2 = sqlSession2.getMapper(StudentMapper.class);
    
        System.out.println(studentMapper.getStudentById(1)); // 查询数据库
        System.out.println(studentMapper.getStudentById(1)); // 查询缓存
        System.out.println(studentMapper2.updateStudentName("小岑",1)); // 更新数据
        System.out.println(studentMapper.getStudentById(1)); // 查询缓存,脏数据
        System.out.println(studentMapper2.getStudentById(1)); // 查询数据库
    }
    

    一级缓存工作流程

    一级缓存执行的时序图,如下图所示。

    img

    总结

    1. MyBatis一级缓存的生命周期和SqlSession一致。
    2. MyBatis一级缓存内部设计简单,只是一个没有容量限定的HashMap,在缓存的功能性上有所欠缺。
    3. MyBatis的一级缓存最大范围是SqlSession内部,有多个SqlSession或者分布式的环境下,数据库写操作会引起脏数据,所以建议设定缓存级别为Statement
  • 相关阅读:
    ubuntu16.04下安装Wineqq+Firefox flash安装+搜狗输入法+截图软件ksnatshot
    集合数据类型
    hadoop2.7ubuntu伪分布式搭建
    广播变量&累加变量
    第一行代码----服务的最佳实践(体会,问题,解决)
    c语言中产生随机数
    如何把StringBuilder类型字符串中的字符换位置
    判断字母的大小写方法(3种)
    方法的参数个数讨论。
    中缀表达式->后缀表达式
  • 原文地址:https://www.cnblogs.com/danhuang/p/12782180.html
Copyright © 2020-2023  润新知