首页 专题 文章 代码 归档
Mybatis的缓存
2020.02.06 14:14 2020.02.06 14:21

1. 缓存机制

MyBatis包含一个非常强大的查询缓存特性,它可以非常方便地配置和定制。缓存可以极大的提升查询效率!


mybatis的缓存机制有两级:

  • 一级缓存:一级缓存mybatsi已近为我们自动开启,不用我们手动操作,而且我们是关闭不了的!!但是我们可以手动清除缓存。(SqlSession级别,本地缓存)
  • 二级缓存:二级缓存需要我们手动开启。(全局级别,全局缓存)

为了提高扩展性。MyBatis定义了缓存接口Cache。我们可以通过实现Cache接口来自定义二级缓存。

1.1. 一级缓存

我们来测试一下:

@Test
public void testCache() throws IOException {
    SqlSession sqlSession = getSqlSession();

    EmployeeCacheMapper mapper = sqlSession.getMapper(EmployeeCacheMapper.class);
    Employee byId = mapper.findById(5);
    //2
    Employee byId2 = mapper.findById(5);

    System.out.println("byId = " + byId);
    System.out.println("byId2 = " + byId2);
    System.out.println(byId == byId2);
    sqlSession.commit();
}

测试结果:

Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@548e6d58]
==>  Preparing: select * from employee where id = ?; 
==> Parameters: 5(Integer)
<==    Columns: id, last_name, email, gender, dept_id
<==        Row: 5, Tom, admin1@misiai.com, 男, 1
<==      Total: 1
byId = Employee{id=5, lastName='Tom', email='admin1@misiai.com', gender='男', department=null}
byId2 = Employee{id=5, lastName='Tom', email='admin1@misiai.com', gender='男', department=null}
true

结论:

1、SQL语句只打印了一次

2、byId=byId2,也即该对象是同一个。

3、自动开启一级缓存(SqlSession级别)


失效情况:

1、SqlSession不同。

2、SqlSession相同,查询条件不同。

3、SqlSession相同,两次查询之间执行了增删改操作。

4、SqlSession相同,手动清空一级缓存。sqlSession.clearCache();

1.2. 二级缓存

全局缓存,基于namespace的缓存,一个namespace,一个缓存。

工作机制:

1、一个会话,查询一条数据,这个数据就会被放在当前会话的一级缓存中;

2、如果会话关闭;一级缓存中的数据会被保存到二级缓存中;新的会话查询信息,就可以参照二级缓存;


使用:

1、在全局配置文件中,开启:

<settings>
    <setting name="cacheEnabled" value="true"/>
</settings>

2、在mapper中开:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.misiai.dao.EmployeeCacheMapper">
    <!--cache开启缓存-->
    <cache/>
</mapper>

cache属性:

  • eviction:缓存的回收策略:
    • LRU-最近最少使用的:移除最长时间不被使用的对象。
    • FIFO-先进先出:按对象进入缓存的顺序来移除它们。
    • SOFT-软引用:移除基于垃圾回收器状态和软引用规则的对象。
    • WEAK-弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
    • 默认的是LRU。
  • flushInterval:缓存刷新间隔缓存多长时间清空一次,默认不清空,设置一个毫秒值
  • readOnly:是否只读;
    • true:只读;
      • mybatis认为所有从缓存中获取数据的操作都是只读操作,不会修改数据。
      • mybatis为了加快获取速度,直接就会将数据在缓存中的引用交给用户。不安全,速度快
    • false:非只读;mybatis觉得获取的数据可能会被修改。
      • mybatis会利用序列化&反序列的技术克隆一份新的数据给你。安全,速度慢I

测试

@Test
   public void testCache() throws IOException {

       String resource = "mybatis-config.xml";
       InputStream inputStream = Resources.getResourceAsStream(resource);
       SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

       /*测试二级缓存*/

       SqlSession sqlSession = sqlSessionFactory.openSession();
       EmployeeCacheMapper mapper = sqlSession.getMapper(EmployeeCacheMapper.class);

       SqlSession sqlSession2 = sqlSessionFactory.openSession();
       EmployeeCacheMapper mapper2 = sqlSession2.getMapper(EmployeeCacheMapper.class);

       //1
       Employee byId = mapper.findById(5);
       System.out.println("byId = " + byId);
       // 这里先必须关闭了,才有缓存。
       sqlSession.close();
       //2
       Employee byId2 = mapper2.findById(5);
       System.out.println("byId2 = " + byId2);
       sqlSession2.close();

   }

细节:

必须是第一次会话关闭后,然后再进行第二次会话查询,才有缓存。


和缓存有关的设置/属性:

1、cacheEnabled=true;false:关闭缓存(二级缓存关闭)(一级缓存一直可用的)

2、每个select标签都有useCache="true";false:不使用缓存(一级缓存依然使用,二级缓存不使用)

3、每个增删改标签的:flushCache="true":增删改执行完成后就会清除缓存;

测试:flushcache="true"一级缓存就清空了;二级缓存也会被清除。

4、sqlSession.clearCache();只是清除当前session的一级缓存;

本节阅读完毕! (分享
二维码图片 扫描关注我们哟