ehcache作为Mybatis二级缓存的问题
来源:互联网 发布:易约软件 编辑:程序博客网 时间:2024/05/29 19:24
在项目中曾经出现mybatis-ehcache做二级缓存导致数据脏读的问题。在读场景居多的情况下,这种方式可以提高了缓存命中率。但是在实际应用场景下,开发规范不可控,坑可能更多些。。。
<!-- ecache --> <dependency> <groupId>com.googlecode.ehcache-spring-annotations</groupId> <artifactId>ehcache-spring-annotations</artifactId> <version>1.1.2</version> <type>jar</type> <scope>compile</scope> </dependency> <dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache-core</artifactId> <version>2.1.0</version> </dependency> <!-- https://mvnrepository.com/artifact/org.mybatis.caches/mybatis-ehcache --> <dependency> <groupId>org.mybatis.caches</groupId> <artifactId>mybatis-ehcache</artifactId> <version>1.0.3</version> </dependency> <!-- ecache -->
一般会配置如下的pom,然后配置好ehcache与Mapper文件就可以了。这里边会引用mybatis-ehcache。
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
Mybatis本身只支持一级缓存,提供二级缓存的接入能力。当有更新产生时,会清空一二级缓存,借个网上的图说明下缓存架构
这里有个关键点二级缓存是基于mapper映射文件的namespace。可以查看org.mybatis.caches.ehcache.EhcacheCache源码
public final class EhcacheCache implements Cache { /** * The cache manager reference. */ private static final CacheManager CACHE_MANAGER = CacheManager.create(); /** * The cache id (namespace) */ private final String id; /** * The cache instance */ private final Ehcache cache; /** * Dummy lock that actually does not lock. * As of 3.2.6 MyBatis does not call locking methods. */ private final ReadWriteLock readWriteLock = new DummyReadWriteLock();
EhcacheCache继承了Mybatis的org.apache.ibatis.cache.Cache接口。其中的cacheId即为Mapper文件的namespace。而mybatis 对cache的管理是通过cacheId来做的。
我们看下Mybatis创建cache,此部分在org.apache.ibatis.builder.MapperBuilderAssistant。
public Cache useNewCache(Class<? extends Cache> typeClass, Class<? extends Cache> evictionClass, Long flushInterval, Integer size, boolean readWrite, Properties props) { typeClass = valueOrDefault(typeClass, PerpetualCache.class); evictionClass = valueOrDefault(evictionClass, LruCache.class); Cache cache = new CacheBuilder(currentNamespace) .implementation(typeClass) .addDecorator(evictionClass) .clearInterval(flushInterval) .size(size) .readWrite(readWrite) .properties(props) .build(); configuration.addCache(cache); currentCache = cache; return cache; }
configuration.addCache(cache)是在org.apache.ibatis.session.Configuration中添加cache的
public void addCache(Cache cache) { caches.put(cache.getId(), cache); }
此处的cacheId即为org.mybatis.caches.ehcache.EhcacheCache中的id值。
在org.apache.ibatis.executor.CachingExecutor可以看到Mybatis的清除cache执行方法。
private void flushCacheIfRequired(MappedStatement ms) { Cache cache = ms.getCache(); if (cache != null && ms.isFlushCacheRequired()) { tcm.clear(cache); } }
cache从属于MappedStatement,每个ms对应一个mapper文件的命名空间。Mybatis是在不同的namesapce下对各自的cache进行操作的。
从而mybatis在ehcache作为缓存情况下出现多表或者关联查询时,将很可能出现脏数据。那位同学就是因为在一个mapper中关联查询,关联表更新,但是对应这个mapper 中的cache还是原来的导致的脏读问题。
总的来看这种二级缓存方式弊要大于利。
1、这种方式基于mapper的namespace区分,要能确保开发人员在一个mapper中不引入其他的表。如果出现关联查询则更难处理。
2、使用场景非常有限,需要读远超过其他三种方式。
综上,建议还是在业务逻辑层加入缓存,而尽量谨慎选择Mybatis的二级缓存方式。
- ehcache作为Mybatis二级缓存的问题
- MyBatis组合EhCache二级缓存
- mybatis二级缓存之ehcache
- Mybatis的二级缓存问题
- mybatis整合ehcache分布式二级缓存框架的使用
- 二级缓存ehcache的使用方法
- redis作为mybatis的二级缓存,此时二级缓存可以作为高并发缓存吗
- Mybatis使用OSCache和EHcache实现二级缓存
- Mybatis使用OSCache和EHcache实现二级缓存
- 【MyBatis框架】查询缓存-二级缓存-整合ehcache
- mybatis二级缓存应用及与ehcache整合
- mybatis一二级缓存详解,整合ehcache缓存,
- mybatis二级缓存应用及与ehcache整合
- 【MyBatis框架】查询缓存-二级缓存-整合ehcache
- MyBatis--查询缓存--ehcache二级缓存配置
- MyBatis--查询缓存--ehcache二级缓存配置文件详解
- 【MyBatis框架】查询缓存-二级缓存-整合ehcache
- Spring Boot + Mybatis + Ehcache 二级缓存实例
- JavaWeb: Spring框架学习1
- Context都没弄明白,还怎么做Android开发?
- javaEE之数据库及数据源
- python简介---2017-7-17
- java 经典题 /百钱买百鸡 /斐波那契
- ehcache作为Mybatis二级缓存的问题
- git命令笔记及常见问题记录
- 百练_2677:肿瘤检测
- Java异常机制
- selenium中文文档
- Android创建窗口(一)创建应用窗口
- DataTable的一些总结
- MarkDown编辑器是什么
- Java基础加强总结(一)——注解(Annotation)