• MyBatis 缓存机制


    1. 概述

    1.1 缓存可以极大的提升查询效率,MyBatis 系统中默认定义了两级缓存:一级缓存和二级缓存
    • 默认情况下,只有一级缓存(SqlSession 级别的缓存,也称为本地缓存)开启;
    • 二级缓存(基于namespace 级别的缓存, 也称为全局缓存)需要手动开启和配置;
    • 为了提高扩展性,MyBatis 定义了缓存接口 Cache, 可以通过实现Cache 接口来自定义二级缓存;

    2. 一级缓存

    • 一级缓存: 与数据库同一次会话期间,查询到的数据会放在本地缓存中;以后,如果需要获取相同的数据,直接从缓存中获取;
    • 一级缓存就是SqlSession级别的一个Map;
    • 一级缓存失效的情况(即获取相同的数据,需要发送两次sql语句)
      • SqlSession 不同时,一级缓存失效;
      • SqlSession 相同,查询条件不同;
      • SqlSession 相同,但是两次查询之间,执行了增删改操作;
      • SqlSession 相同,手动清除了一级缓存;(clearCache() 方法)
    // EmployeeMapper.java
    public class EmployeeMapper{
    
        public Employee getEmpById(Integer id);
    }
    
    // EmployeeMapper.xml
    <resultMap type="cn.itcast.mybatis.bean.Employee" id="MyEmp">
        <id column="id" property="id"/>
        <result column="last_name" property="lastName"/>
    </resultMap>
    
    <select id="getEmpById" resultMap="MyEmp">
        select * from tbl_employee where id=#{id}
    </select>
    
    // 测试类
    public class MyTest{
    
        @Test
        public void test01 throw IOException{
            SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
    
            SqlSession openSession = sqlSessionFactory.openSession();
    
            try{
                EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
    
                // 一级缓存
                Employee emp01 = mapper.getEmpById(1);
                System.out.println(emp01);
    
                Employee emp02 = mapper.getEmpById(1);
                System.out.println(emp02);
                System.out.println(emp01==emp02);
    
            }finally{
                openSession.close();
            }
        }
    }
    

    3. 二级缓存

    1. 基于namespace级别的缓存,一个namespace对应一个二级缓存;
    2. 查询出的数据,都会默认放在一级缓存中,只有会话提交或关闭之后,一级缓存中的数据才会转移到二级缓存;
    3. 工作机制:
      • 一个会话查询一条数据,这个数据就会被放在当前会话的一级缓存中;
      • 如果会话关闭,一级缓存中的数据会被保存到二级缓存中; 新的会话查询信息,就可以参照二级缓存中的内容;
      • 例如,使用EmployeeMapper对象,查询到的Employee对象, 和使用DepartmentMapper对象,查询到
        的Department对象分别存放在不同的map中;即不同namespace查询出的数据,会放在自己对应的缓存(map);
    4. 使用步骤:
      • mybatis-config.xml中开启: <setting name="cacheEnabled" value="true"/>;
      • xxxMapper.xml 中配置使用二级缓存:<cache></cache>,常用属性:
        • eviction: 缓存的回收策略;(LRU, FIFO, SOFT, WEAK)
        • flushInterval: 缓存刷新间隔; 即缓存多长时间清空一次,默认不清空;
        • readOnly: 缓存是否只读;
        • size: 缓存存放多少元素;
        • type: 指定自定义缓存的全类名;
      • POJO 需要实现序列化接口;
    5. 和缓存相关的设置/属性:
      • cacheEnabled=false: 关闭的是二级缓存,一级缓存仍可用;
      • select 标签中的 useCache=false: 关闭的也是二级缓存,一级缓存依然可以使用;
      • 每个增删改标签都存在 flushCache=true,默认为true; 表示增删改执行完成后,就会清空一级缓存和二级缓存;
      • 查询标签的fluseCache的属性默认为 false;
      • sqlSession.clearCache(): 只清空当前session中的一级缓存;
    // 测试类
    public class MyTest{
    
        @Test
        public void test01 throw IOException{
            SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
    
            SqlSession openSession = sqlSessionFactory.openSession();
            SqlSession openSession2 = sqlSessionFactory.openSession();
    
            try{
                EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
                EmployeeMapper mapper2 = openSession2.getMapper(EmployeeMapper.class);
    
                // 两次会话,查询内容相同; 二级缓存开启的情况下,只会发送一条SQL语句
                Employee emp01 = mapper.getEmpById(1);
                System.out.println(emp01);
                openSession.close();
    
                Employee emp02 = mapper2.getEmpById(1);
                System.out.println(emp02);
                openSession2.close();
    
            }finally{
    
            }
        }
    }
    

    4. 整合第三方缓存(ehcache)

    1. 导入jar包: ehcache-core-2.6.8, slf4j-api, slf4j-log4j, mybatis-ehcache;
    2. 配置 EmployeeMapper.xml
    3. 在类路径下新建ehcache.xml文件
    // EmployeeMapper.xml
    <mapper namespace="cn.itcast.mybatis.dao.EmployeeMapper">
    
    <cache type="org.mybatis.caches.ehcache.EhcacheCache"></cache>
    
    <resultMap type="cn.itcast.mybatis.bean.Employee" id="MyEmp">
        <id column="id" property="id"/>
        <result column="last_name" property="lastName"/>
    </resultMap>
    
    <select id="getEmpById" resultMap="MyEmp">
        select * from tbl_employee where id=#{id}
    </select>
    </mapper>
    
    // DepartmentMapper.xml
    <mapper namespace="cn.itcast.mybatis.dao.DepartmentMapper">
    
    <!-- 引用缓存: namespace,指定和哪个名称空间下的缓存一样 -->
    <cache-ref namespace="cn.itcast.mybatis.dao.EmployeeMapper"/>
    
    <resultMap type="cn.itcast.mybatis.bean.Employee" id="MyEmp">
        <id column="id" property="id"/>
        <result column="last_name" property="lastName"/>
    </resultMap>
    
    <select id="getEmpById" resultMap="MyEmp">
        select * from tbl_employee where id=#{id}
    </select>
    </mapper>
    

    参考资料

  • 相关阅读:
    usaco-4.1-nuggets-passed
    usaco-3.4-rockers-passed
    usaco-3.4-fence9-passed
    usaco-3.4-heritage-passed
    usaco-3.3-game1-passed
    usaco-3.3-range-passed
    usaco-3.3-camelot-passed
    6.23课堂作业
    初识JVM虚拟机
    JDK安装以及配置环境变量的步骤
  • 原文地址:https://www.cnblogs.com/linkworld/p/7795658.html
Copyright © 2020-2023  润新知