Java学习-MyBatis缓存

MyBatis缓存

MyBatis一级缓存
  • 一级缓存是SqlSession级别的,通过同一个SqlSession查询的数据会被缓存,下次查询相同的数据,就会从缓存中直接获取,不会去访问数据库
  • 一级缓存失效的四种情况
    • 不同的SqlSession对应不同的一级缓存
    • 同一个SqlSession但查询条件不同
    • 同一个SqlSession两次查询期间执行了任何一次增删改操作
    • 同一个SqlSession两次查询期间手动清除了缓存
  @Test
    public void testGetEmp() {
        SqlSession sqlSession1 = SqlSessionUtils.getSqlSession();
        CacheMapper mapper1 = sqlSession1.getMapper(CacheMapper.class);
        Emp emp1 = mapper1.getEmpById(4);
        System.out.println(emp1);
        //手动清空缓存
        sqlSession1.clearCache();
        Emp emp2 = mapper1.getEmpById(4);
        System.out.println(emp2);
        //执行插入操作
        mapper1.insertEmp(new Emp(null,"jack",23,"男","jack@qq.com"));
        CacheMapper mapper2 = sqlSession1.getMapper(CacheMapper.class);
        Emp emp3 = mapper2.getEmpById(4);
        System.out.println(emp3);
        //使用不同的SqlSession
        SqlSession sqlSession2 = SqlSessionUtils.getSqlSession();
        CacheMapper mapper3 = sqlSession2.getMapper(CacheMapper.class);
        Emp emp4 = mapper3.getEmpById(4);
        System.out.println(emp4);
    }
/*
  ①不同的SqlSession查询相同的数据缓存失效
  ②同一个SqlSession两次查询期间执行了插入操作,导致缓存失效
  ③同一个SqlSession两次查询期间手动清空了缓存
*/
DEBUG 06-14 14:45:16,001 ==>  Preparing: select * from t_emp where eid=? (BaseJdbcLogger.java:137) 
DEBUG 06-14 14:45:16,021 ==> Parameters: 4(Integer) (BaseJdbcLogger.java:137) 
DEBUG 06-14 14:45:16,048 <==      Total: 1 (BaseJdbcLogger.java:137) 
Emp{eid=4, empName='tye', age=14, sex='男', email='tye@qq.com', dept=null}
DEBUG 06-14 14:45:16,048 ==>  Preparing: select * from t_emp where eid=? (BaseJdbcLogger.java:137) 
DEBUG 06-14 14:45:16,048 ==> Parameters: 4(Integer) (BaseJdbcLogger.java:137) 
DEBUG 06-14 14:45:16,048 <==      Total: 1 (BaseJdbcLogger.java:137) 
Emp{eid=4, empName='tye', age=14, sex='男', email='tye@qq.com', dept=null}
DEBUG 06-14 14:45:16,048 ==>  Preparing: insert into t_emp(eid,emp_name,age,sex,email) values(null,?,?,?,?); (BaseJdbcLogger.java:137) 
DEBUG 06-14 14:45:16,048 ==> Parameters: jack(String), 23(Integer),(String), jack@qq.com(String) (BaseJdbcLogger.java:137) 
DEBUG 06-14 14:45:16,056 <==    Updates: 1 (BaseJdbcLogger.java:137) 
DEBUG 06-14 14:45:16,056 ==>  Preparing: select * from t_emp where eid=? (BaseJdbcLogger.java:137) 
DEBUG 06-14 14:45:16,056 ==> Parameters: 4(Integer) (BaseJdbcLogger.java:137) 
DEBUG 06-14 14:45:16,056 <==      Total: 1 (BaseJdbcLogger.java:137) 
Emp{eid=4, empName='tye', age=14, sex='男', email='tye@qq.com', dept=null}
DEBUG 06-14 14:45:16,111 ==>  Preparing: select * from t_emp where eid=? (BaseJdbcLogger.java:137) 
DEBUG 06-14 14:45:16,111 ==> Parameters: 4(Integer) (BaseJdbcLogger.java:137) 
DEBUG 06-14 14:45:16,127 <==      Total: 1 (BaseJdbcLogger.java:137) 
Emp{eid=4, empName='tye', age=14, sex='男', email='tye@qq.com', dept=null}
MyBatis二级缓存
  • 二级缓存是SqlSessionFactory级别,通过同一个SqlSessionFactory创建的SqlSession查询的结果会被缓存,此后再执行相同查询,结果就会从缓存中获取
  • 二级缓存开启条件:
    • 在核心配置文件中,设置全局配置属性cacheEnabled=“true”,默认为true,不需要设置
    • 在映射文件中设置标签
    • 二级缓存必须在SqlSession关闭或提交之后有效
    • 查询的数据所转换的实体类型必须实现序列化的接口
//上述条件缺一不可
@Test
    public void testTwoCache() throws IOException {
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
        SqlSession sqlSession1 = sqlSessionFactory.openSession(true);
        CacheMapper mapper1 = sqlSession1.getMapper(CacheMapper.class);
        System.out.println(mapper1.getEmpById(4));
        sqlSession1.close();
        SqlSession sqlSession2 = sqlSessionFactory.openSession(true);
        CacheMapper mapper2 = sqlSession2.getMapper(CacheMapper.class);
        System.out.println(mapper2.getEmpById(4));
        sqlSession2.close();
    }
//执行结果
DEBUG 06-14 15:23:18,059 Cache Hit Ratio [com.lotus.mybatis.mapper.CacheMapper]: 0.0 (LoggingCache.java:60) 
DEBUG 06-14 15:23:18,968 ==>  Preparing: select * from t_emp where eid=? (BaseJdbcLogger.java:137) 
DEBUG 06-14 15:23:18,984 ==> Parameters: 4(Integer) (BaseJdbcLogger.java:137) 
DEBUG 06-14 15:23:19,015 <==      Total: 1 (BaseJdbcLogger.java:137) 
Emp{eid=4, empName='tye', age=14, sex='男', email='tye@qq.com', dept=null}
WARN  06-14 15:23:19,015 As you are using functionality that deserializes object streams, it is recommended to define the JEP-290 serial filter. Please refer to https://docs.oracle.com/pls/topic/lookup?ctx=javase15&id=GUID-8296D8E8-2B93-4B9A-856E-0A65AF9B8C66 (SerialFilterChecker.java:46) 
DEBUG 06-14 15:23:19,015 Cache Hit Ratio [com.lotus.mybatis.mapper.CacheMapper]: 0.5 (LoggingCache.java:60) 
Emp{eid=4, empName='tye', age=14, sex='男', email='tye@qq.com', dept=null}
  • 二级缓存失效情况
    • 两次查询期间执行了任何一次增删改操作,会使一级和二级缓存同时失效
二级缓存相关配置
  • 在mapper配置文件中添加的cache标签可以设置一些属性
    • eviction属性:缓存回收策略
      • LRU(Least Recently Used) :最近最少使用,移除最长时间不被使用的对象
      • FIFO(First In First Out):先进先出,按对象进入缓存的顺序来移除它们
      • SOFT:软引用,移除基于垃圾回收器状态和软引用规则的对象
      • WEAK:弱引用,更积极地移除基于垃圾收集器状态和弱引用规则的对象
      • 默认LRU
    • flushInterval属性:刷新间隔,单位毫秒
      • 默认不设置,也就是无刷新间隔,缓存仅调用语句时刷新
    • size属性:引用数目,正整数
      • 代表缓存最多可以存储多少个对象,太大容易导致内存溢出
    • readOnly属性:只读,true|false
      • true:只读缓存,会给所有调用者返回缓存对象的相同实例,因此这些对象不能被修改,提供了很重要的性能优势
      • false:读写缓存,会返回缓存对象的拷贝(通过序列化),会慢一些,但安全,默认为false
缓存查询顺序
  • ①先查询二级缓存,二级缓存中可能会有其他程序已经查出来的数据,可以拿来直接使用
  • ②如果二级缓存没有命中,再查询一级缓存
  • ③如果一级缓存也没有命中,则查询数据库
  • ④SqlSession关闭之后,一级缓存中的数据会导入二级缓存
整合第三方缓存EHCache
<!-- Mybatis EHCache整合 -->
<dependency>
    <groupId>org.mybatis.caches</groupId>
    <artifactId>mybatis-ehcache</artifactId>
   <version>1.2.1</version>
</dependency>
<!-- slf4j日志门面的一个具体实现 -->
<dependency>
   <groupId>ch.qos.logback</groupId>
   <artifactId>logback-classic</artifactId>
   <version>1.2.3</version>
</dependency>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值