Mybaits 缓存

Mybatis 缓存

Mybatis 缓存分为一级缓存和二级缓存,其中一级缓存为sqlSession级别的缓存,二级缓存为Mapper级别的缓存。

 

一级缓存

1. 通过Mybatis访问数据库默认每次都会新建一个sqlSession,如果两次数据访问处于一个事务中,那么获取到的就是同一个sqlSession

( 源码位置:org.mybatis.spring.SqlSessionUtils.getSqlSession(SqlSessionFactory, ExecutorType, PersistenceExceptionTranslator) )。

 

2. sqlSession最终的缓存结构为一个Map,Key的类型为CacheKey,

其生成规则为 mappedStementId + offset + limit + SQL + queryParams + environment ,示例:com.focustech.silk.Mapper.getUser:0:2147483647:select * from users where id = ?:123:development

其中粗体部分为变化部分,用相同的参数调取同一Mapper中的方法,CacheKey肯定是相等的。

(源码位置:org.apache.ibatis.executor.BaseExecutor.createCacheKey(MappedStatement, Object, RowBounds, BoundSql))

 

3.Mybatis默认是开启一级缓存的,用于加速重复查询。可以使用参数关闭。

  全局关闭:可以在Mybatis配置文件中加入 <setting name="localCacheScope" value="STATEMENT"/>

 针对某一个语句关闭:可以在sql标签中加入 flushCache="true"

(源码位置:org.apache.ibatis.executor.BaseExecutor.query(MappedStatement, Object, RowBounds, ResultHandler, CacheKey, BoundSql))

 

4.一级缓存的刷新,如果执行了数据更新操作,首先会清空本地缓存,防止取到脏数据。

(源码位置:org.apache.ibatis.executor.BaseExecutor.update(MappedStatement, Object))

 

5.:某些业务场景下,需要通过一个sql 多次从Oracle数据库根据Sequence获取主键,如果你正好开启了事务,那么多次获取的主键始终是同一个数值。这个时候就需要指定该statement需要刷新缓存。

 

二级缓存

1.二级缓存的作用域是Mapper的Namespace,同一个Mapper下的所有sql共享同一个缓存。

(源码位置:org.apache.ibatis.builder.MapperBuilderAssistant.useNewCache(Class<? extends Cache>, Class<? extends Cache>, Long, Integer, boolean, boolean, Properties))

 

2.二级缓存需要通过添加<cache>标签来开启,例如可以在Mapper中添加以下内容来开启。 <cache  eviction="FIFO"  flushInterval="60000"  size="512"  readOnly="true"/>

  eviction:缓存回收策略 默认的是 LRU。可选项为:LRU FIFO SOFT WEAK

  flushInterval:缓存刷新间隔(单位为毫秒)默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新。

  size: 结果引用个数。默认值是 1024。

  readonly:只读的缓存会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。可读写的缓存 会返回缓存对象的拷贝(通过序列化) 。这会慢一些,但是安全,因此默认是 false。

 

3.Mybatis二级缓存可以使用参数关闭。

  全局关闭:可以在Mybatis配置文件中加入 <setting name="cacheEnabled" value="false"/>

  针对某一个语句关闭:可以在sql标签中加入 useCache="false"

(源码位置:org.apache.ibatis.executor.CachingExecutor.query(MappedStatement, Object, RowBounds, ResultHandler, CacheKey, BoundSql))

 

4.二级缓存的刷新,如果执行了数据更新操作,在commit的时候,会清空整个Mapper的缓存

(源码位置:org.apache.ibatis.executor.CachingExecutor.close(boolean))

 

5.注意事项:

二级缓存力度很粗,有一个sql执行了更新操作,整个Mapper的缓存就会被清空。

只能应用于数据实时性要求不高的场景,因为可能存在多个应用同时在对数据库做修改,此时如果使用二级缓存很容易出现过时数据。

 

参考文献:

Mybatis中文文档官网 

深入了解MyBatis二级缓存

posted @ 2017-08-30 17:33  nozbwang  阅读(203)  评论(0编辑  收藏  举报