mybatis 学习五 二级缓存不推荐使用

mybatis 二级缓存不推荐使用

    一 mybatis的缓存使用。

大致就是首先根据你的sqlid,参数的信息本身算出一个key值,而后你查询的时候,会先把这个key值去缓存中找看有没有value,若是有,直接返回出来,就不查询db了。若是没有,那么查询db,而后将key,value保存到缓存中,以便下次使用。

     1.1mybatis的一级缓存是基于sqlsession为生命周期的

当你这个session没有了,缓存就没有了,其次当你sql执行!isselect语句的时候,缓存也会被直接所有清理掉以保证数据一致性。
  public int update(MappedStatement ms, Object parameter) throws SQLException {
    ErrorContext.instance().resource(ms.getResource()).activity("executing an update").object(ms.getId());
    if (closed) throw new ExecutorException("Executor was closed.");
     //清理缓存
    clearLocalCache();
    return doUpdate(ms, parameter);
  }

 

     1.2 mybatis的二级缓存是基于application为生命周期的

范围是按照每一个namepace一个缓存来存贮和维护,同一个namespace放到一个缓存对象中,当这个namaspace中执行了!isselect语句的时候,整个namespace中的缓存所有清除掉。
  public int update(MappedStatement ms, Object parameterObject) throws SQLException {
     //清理缓存,而且!isselect语句的flushcache都是默认为true的。
    flushCacheIfRequired(ms);
    return delegate.update(ms, parameterObject);
  }

 

 
如下摘抄自网络观点文字  http://blog.csdn.net/isea533/article/details/44566257

     3、Cache使用时的注意事项


1. 只能在【只有单表操做】的表上使用缓存

不仅是要保证这个表在整个系统中只有单表操做,并且和该表有关的所有操做必须所有在一个namespace下。

2. 在能够保证查询远远大于insert,update,delete操做的状况下使用缓存

这一点不须要多说,全部人都应该清楚。记住,这一点须要保证在1的前提下才能够!

4、避免使用二级缓存


可能会有不少人不理解这里,二级缓存带来的好处远远比不上他所隐藏的危害。

缓存是以namespace为单位的,不一样namespace下的操做互不影响。

insert,update,delete操做会清空所在namespace下的所有缓存。

一般使用MyBatis Generator生成的代码中,都是各个表独立的,每一个表都有本身的namespace。

为何避免使用二级缓存

在符合【Cache使用时的注意事项】的要求时,并无什么危害。

其余状况就会有不少危害了。

针对一个表的某些操做不在他独立的namespace下进行。

例如在UserMapper.xml中有大多数针对user表的操做。可是在一个XXXMapper.xml中,还有针对user单表的操做。

这会致使user在两个命名空间下的数据不一致。若是在UserMapper.xml中作了刷新缓存的操做,在XXXMapper.xml中缓存仍然有效,若是有针对user的单表查询,使用缓存的结果可能会不正确。

更危险的状况是在XXXMapper.xml作了insert,update,delete操做时,会致使UserMapper.xml中的各类操做充满未知和风险。

有关这样单表的操做可能不常见。可是你也许想到了一种常见的状况。

多表操做必定不能使用缓存

为何不能?

首先无论多表操做写到那个namespace下,都会存在某个表不在这个namespace下的状况。

例如两个表:role和user_role,若是我想查询出某个用户的所有角色role,就必定会涉及到多表的操做。

<select id="selectUserRoles" resultType="UserRoleVO">
    select * from user_role a,role b where a.roleid = b.roleid and a.userid = #{userid}
</select>

 

像上面这个查询,你会写到那个xml中呢??

无论是写到RoleMapper.xml仍是UserRoleMapper.xml,或者是一个独立的XxxMapper.xml中。若是使用了二级缓存,都会致使上面这个查询结果可能不正确。

若是你正好修改了这个用户的角色,上面这个查询使用缓存的时候结果就是错的。

这点应该很容易理解。

在我看来,就以MyBatis目前的缓存方式来看是无解的。多表操做根本不能缓存。

若是你让他们都使用同一个namespace(经过<cache-ref>)来避免脏数据,那就失去了缓存的意义。

看到这里,实际上就是说,二级缓存不能用。整篇文章介绍这么多也没什么用了。


5、挽救二级缓存?


想更高效率的使用二级缓存是解决不了了。

可是解决多表操做避免脏数据仍是有法解决的。解决思路就是经过拦截器判断执行的sql涉及到那些表(能够用jsqlparser解析),而后把相关表的缓存自动清空。可是这种方式对缓存的使用效率是很低的。

设计这样一个插件是至关复杂的,既然我没想着去实现,就不废话了。

最后仍是建议,放弃二级缓存,在业务层使用可控制的缓存代替更好。
相关文章
相关标签/搜索