MyBatis的二级缓存

二级缓存全局缓存,基于namespace级别的缓存,一个namespace对应于一个二级缓存。

工作机制

  • 一个会话,查询一条数据,这个数据就会被放在当前会话的一级缓存中。
  • 如果当前会话关闭,一级缓存数据会被保存到二级缓存中,新的会话查询就会查询二级缓存的数据。
  • sqlSession 对应了EdptMapper(namespace)和EmployeeMapper 一个namespace对应一个二级缓存

使用

  1. 开启二级缓存全局配置

    <!-- mybatis-config.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configuration
         PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
         "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
    <settings>
     <!-- 这个配置使全局的映射器启用或禁用缓存 -->
     <setting name="cacheEnabled" value="true" />
    </configuration> 
  2. 去xxxxmapper.xml中配置使用二级缓存

    <!-- mybatis-config.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
         PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="cn.fulong.mybatis.emp.dao.DeptMapper" >
    <cache eviction="" flushInterval="" size="" readOnly="" />
    <!--
    eviction:
         + LRU  – 最近最少使用:移除最长时间不被使用的对象。
         + FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
         + SOFT – 软引用:基于垃圾回收器状态和软引用规则移除对象。
         + WEAK – 弱引用:更积极地基于垃圾收集器状态和弱引用规则移除对象。默认的清除策略是 LRU。
    flushInterval:(刷新间隔)属性可以被设置为任意的正整数,设置的值应该是一个以毫秒为单位的合理时间量。 默认情况是不设置,也就是没有刷新间隔,缓存仅仅会在调用语句时刷新。
    size:(引用数目)属性可以被设置为任意正整数,要注意欲缓存对象的大小和运行环境中可用的内存资源。默认值是 1024。
    readOnly:(只读)属性可以被设置为 true 或 false。只读的缓存会给所有调用者返回缓存对象的相同实例。 因此这些对象不能被修改。这就提供了可观的性能提升。而可读写的缓存会(通过序列化)返回缓存对象的拷贝。 速度上会慢一些,但是更安全,因此默认值是 false。
    
    -->
    </mpper>
  3. 实体实现序列化接口

    public class Dept implements Serializable {

缓存相关的设置

  1. cacheEnabled=true/false 和二级缓存有关(一级缓存默认开启的)
  2. 每个select标签都有userCache=“true”
  3. 每个增删改的标签,flushCache=“true” (一二级缓存都会被清除)
  4. 查询标签默认flushCache=“flase”,显式设置flushCache=“flase”,缓存不会被使用(一二级缓存都会被清空)
  5. sqlSession.clearCache()只会清除当前session的一级缓存
  6. 全局配置文件 setting 标签内的 localCacheScope:本地缓存作用域(一级缓存)SESION(默认)/STATEMENT(禁用一级缓存)

开启二级缓存,不同的sqlSession查询同一个sql

 /***
     * 二级缓存
     * @throws IOException
     */
    @Test
    public void testCache2() throws IOException {
        // 读取类路径 config目录下的 mybatis-config.xml 配置文件 获取mybatis 全局配置  数据库连接 等信息
        String resource = "config/mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        // 必须使用同一个  SqlSessionFactory 获取sqlsession
        SqlSessionFactory sessionFactory=  new SqlSessionFactoryBuilder().build(inputStream);
        // 获取一个 SqlSession
        SqlSession  openSession =sessionFactory.openSession();
        // 获取一个 SqlSession
        SqlSession  sqlSession  = sessionFactory.openSession();
        try {
            //  获取一个映射器
            DeptMapper mapper=  openSession.getMapper(DeptMapper.class);
            //  查询ID为3的部门的信息
            mapper.selectDeptById(3);
            // 关闭Session 必须要关闭session 不然还是走的一级缓存
            openSession.close();
            //  获取一个新的映射器
            DeptMapper mapperNew=  sqlSession.getMapper(DeptMapper.class);
            //  再次查询ID为3的部门的信息
            mapperNew.selectDeptById(3);
        } finally {
            // 关闭Session
            sqlSession.close();
        }
    }

发送了一次sql,缓存被使用了

Created connection 55331187.
Returned connection 55331187 to pool.
Cache Hit Ratio [cn.fulong.mybatis.emp.dao.DeptMapper]: 0.0
Opening JDBC Connection
Checked out connection 55331187 from pool.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@34c4973]
==>  Preparing: select * from tbl_dept where id = ? 
==> Parameters: 3(Integer)
<==    Columns: id, dept_name
<==        Row: 3, 吴国
<==      Total: 1
Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@34c4973]
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@34c4973]
Returned connection 55331187 to pool.
Cache Hit Ratio [cn.fulong.mybatis.emp.dao.DeptMapper]: 0.5

Process finished with exit code 0