下面就是MyBatis中所有缓存的包装汇总:
缓存包装器 | 描述 | 作用 | 装饰条件 |
PerpetualCache | 缓存默认实现类 | - | 基本功能,默认携带 |
LruCache | LRU淘汰策略缓存(默认淘汰策略) | 当缓存达到上限,删除最近最少使用缓存 | eviction=“LRU” |
FifoCache | FIFO淘汰策略缓存 | 当缓存达到上限,删除最先入队的缓存 | eviction=“FIFO” |
SoftCache | JVM软引用淘汰策略缓存 | 基于JVM的SoftReference对象 | eviction=“SOFT” |
WeakCache | JVM弱引用淘汰策略缓存 | 基于JVM的WeakReference对象 | eviction=“WEAK” |
LoggingCache | 带日志功能缓存 | 输出缓存相关日志信息 | 基本功能,默认包装 |
SynchronizedCache | 同步缓存 | 基于synchronized关键字实现,用来解决并发问题 | 基本功能,默认包装 |
BlockingCache | 阻塞缓存 | get/put操作时会加锁,防止并发,基于Java重入锁实现 | blocking=true |
SerializedCache | 支持序列化的缓存 | 通过序列化和反序列化来存储和读取缓存 | readOnly=false(默认) |
ScheduledCache | 定时调度缓存 | 操作缓存时如果缓存已经达到了设置的最长缓存时间时会移除缓存 | flushInterval属性不为空 |
TransactionalCache | 事务缓存 | 在TransactionalCacheManager中用于维护缓存map的value值 | - |
二级缓存应该开启吗
既然一级缓存默认是开启的,而二级缓存是需要我们手动开启的,那么我们什么时候应该开启二级缓存呢?
1、因为所有的update操作(insert,delete,uptede)都会触发缓存的刷新,从而导致二级缓存失效,所以二级缓存适合在读多写少的场景中开启。
2、因为二级缓存针对的是同一个namespace,所以建议是在单表操作的Mapper中使用,或者是在相关表的Mapper文件中共享同一个缓存。
自定义缓存
一级缓存可能存在脏读情况,那么二级缓存是否也可能存在呢?
是的,默认的二级缓存毕竟也是存储在本地缓存,所以对于微服务下是可能出现脏读的情况的,所以这时候我们可能会需要自定义缓存,比如利用redis来存储缓存,而不是存储在本地内存当中。
MyBatis官方提供的第三方缓存
MyBatis官方也提供了一些第三方缓存的支持,如:encache和redis。下面我们以redis为例来演示一下:引入pom文件:
<dependency> <groupId>org.mybatis.caches</groupId> <artifactId>mybatis-redis</artifactId> <version>1.0.0-beta2</version> </dependency>
然后缓存配置如下:
<cache type="org.mybatis.caches.redis.RedisCache"></cache>
然后在默认的resource路径下新建一个redis.properties文件:
host=localhost port=6379 12
然后执行上面的示例,查看Cache,已经被Redis包装:
自己实现二级缓存
如果要实现一个自己的缓存的话,那么我们只需要新建一个类实现Cache接口就好了,然后重写其中的方法,如下:
package com.lonelyWolf.mybatis.cache; import org.apache.ibatis.cache.Cache; public class MyCache implements Cache { @Override public String getId() { return null; } @Override public void putObject(Object o, Object o1) { } @Override public Object getObject(Object o) { return null; } @Override public Object removeObject(Object o) { return null; } @Override public void clear() { } @Override public int getSize() { return 0; } }
上面自定义的缓存中,我们只需要在对应方法,如putObject方法,我们把缓存存到我们想存的地方就行了,方法全部重写之后,然后配置的时候type配上我们自己的类就可以实现了,在这里我们就不做演示了
总结
本文主要分析了MyBatis的缓存是如何实现的,并且分别演示了一级缓存和二级缓存,并分析了一级缓存和二级缓存所存在的问题,最后也介绍了如何使用第三方缓存和如何自定义我们自己的缓存,通过本文,我想大家应该可以彻底掌握MyBatis的缓存工作原理了。