Mybatis缓存-装饰模式

向已有的类添加新功能,通过类的关联关系而不是通过继承,更加灵活。

装饰器模式经典实现:

java.io.InputStream

mybatis中使用了装饰器模式的模块:二级缓存

接口:org.apache.ibatis.cache.Cache

org.apache.ibatis.cache.decorators.BlockingCache等其他实现

BlockingCache实现了Cache并且还拥有一个Cache属性,真正做缓存功能的是delegate属性

Cache所有实现类如下(只有PerpetualCache真实实现了Cache缓存功能,其他类都是对该类的封装)

我们可以在mapper文件里配置当前namespace下的二级缓存策略

例如:

<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true" blocking="true"/>

二级缓存真实缓存类会在解析mapper时被实例化

org.apache.ibatis.builder.xml.XMLConfigBuilder#mapperElement
↓
org.apache.ibatis.builder.xml.XMLMapperBuilder#parse
↓
org.apache.ibatis.builder.xml.XMLMapperBuilder#configurationElement
↓
org.apache.ibatis.builder.xml.XMLMapperBuilder#cacheElement
↓
org.apache.ibatis.builder.MapperBuilderAssistant#useNewCache
↓
org.apache.ibatis.mapping.CacheBuilder#build

这里会根据配置生成对应的Cache类

  public Cache build() {
    setDefaultImplementations();
    Cache cache = newBaseCacheInstance(implementation, id);
    setCacheProperties(cache);
    // issue #352, do not apply decorators to custom caches
    if (PerpetualCache.class.equals(cache.getClass())) {
      for (Class<? extends Cache> decorator : decorators) {
        cache = newCacheDecoratorInstance(decorator, cache);
        setCacheProperties(cache);
      }
      cache = setStandardDecorators(cache);
    } else if (!LoggingCache.class.isAssignableFrom(cache.getClass())) {
      cache = new LoggingCache(cache);
    }
    return cache;
  }

一级缓存与二级缓存

我们可以通过在mybatis主配置文件里配置

<settings>
        <setting name="cacheEnabled" value="true"/>
    </settings>

来开启二级缓存,当然mybatis 是默认开启的;在开启二级缓存后

DefaultSqlSession的executor属性将会实例化成 CachingExecutor类的对象,CachingExecutor对象的delegate才是真正执行查询的执行者,默认情况下是org.apache.ibatis.executor.SimpleExecutor,而SimpleExecutor里的localCache才是一级缓存;整个类结构如下图

 所以二级缓存是在一级缓存前生效的;

但是有一个坑就是:

二级缓存是在sqlsession关闭的时候才会将缓存的对象进行持久化(映射的pojo必须要标记java.io.Serializable),所以在同一个sqlsession里连续执行多条相同sql查询那个二级缓存是不会起作用的,这时起作用的时一级缓存;

二级缓存是namespace级别的缓存,如果在不同的namespace里对相同的数据做了修改,那么就有可能出现幻读的错误,所以不建议使用mybatis 的二级缓存;也可以通过cache-ref的方式来让不同的namespace来共享,降低幻读的概率

可以在应用层面上使用redis来做适合业务的逻辑缓存

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值