Mybatis的缓存机制
缓存
缓存就是将用户经常查询的数据的结果保存在内存当中,这样用户再次查询数据时就可以直接通过缓存获取数据,而不需要通过磁盘读取数据。
缓存的分类
Mybatis
提供了一级缓存和二级缓存。
- 一级缓存:一级缓存又叫本地缓存(默认开启,不允许关闭),用户保存用户在一次会话过程中查询的结果,用户一次会话中只能使用一个
sqlsession
。 - 二级缓存:二级缓存又叫全局缓存,二级缓存是对一个表的结果的一个存储,可以共享给所用针对这张表查询的用户。
Executor
执行器 | 说明 |
---|---|
SimpleExecutor | 最简单的执行器,根据对应的sql直接执行,不会做额外的操作 |
BatchExecutor | 通过批量操作来优化性能。执行批量更新时,由于内部有缓存的实现,使用完后需要调用flushStatements 来清除缓存 |
ReuseExecutor | 可重用的执行器,重用的对象是Statement,也就是说该执行器会缓存同一个sql的Statement,省去Statement的重新创建,优化性能。内部的实现通过一个HashMap来维护Statement对象。由于当前Map只在该session中有效,所以使用完后需要调用flushStatement 来清除Map。 |
CachingExecutor | 二级缓存使用的执行器。 |
一级缓存的原理
Mybatis
使用一级缓存的流程:
- 用户发送指令到
Executor
。 Executor
根据用户需要执行的语句生成MappedStatement
。Executor
优先在LocalCache
中查询是否有对应缓存。若有,则将缓存结果返回;若无,则从数据库中查询并获取数据并写入Local Cache
。
sqlsession提交时会清空本地缓存,防止读取脏数据。
一级缓存失效的原因
- 同一个用户使用不同的
sqlsession
。 - 同一个
sqlsession
使用查询条件不同。 - 在同一次事务中进行了更新操作。
一级缓存注意事项
Mybatis
一级缓存的本质时一个没有容量限定的HashMap
Mybatis
和Spring
整合后进行mapper代理开发,不支持一级缓存。
二级缓存原理
二级缓存通过在用户与Excutor
中添加一个CachingExecutor
实现
二级缓存的使用
-
通过注解
@CacheNamespace
使用二级缓存。/* eviction: 使用的缓存策略 flushInterval: 周期刷新频率(ms) blocking: 请求时是否阻塞缓存 size: 缓存大小 */ @CacheNamespace(eviction = FifoCache.class,flushInterval = 3000,size = 512,blocking = false)
-
通过
mapper.xml
文件的cache
标签配置二级缓存。<!--readOnly: 是否只读,若配置读写,则需要对应实体类能够序列化--> <cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
Cache类
Cache类型 | 说明 |
---|---|
LruCache | 使用最近最久未使用算法淘汰缓存。 |
FifoCache | 使用先进先出淘汰缓存。 |
SynchronizedCache | 同步Cache,实现比较简单,注解使用synchronized修饰方法。 |
LoggingCache | 日志功能,装饰类,用于记录缓存的命中率,如果开启了DEBUG模式,则会输出命中率日志。 |
SerializedCache | 序列化功能,将值序列化后存入缓存中,该功能用户缓存返回示例的Cope,用于保存线程安全。 |
PerpetualCache | 最基础的缓存类,底层实现比较简单,直接使用HashMap |
SoftCache | 软引用回收缓存。 |
WeakCache | 弱引用回收缓存。 |
在xml文件中的、、等标签中可以设置flushCache
选择是否刷新缓存,useCache
选择是否使用缓存。
<select flushCache="true" useCache="true">
{sql}查询语句
</select>
二级缓存失效的原因
xml
{sql}查询语句
### 二级缓存失效的原因
`flushCache`属性在增删查改中的使用。