• 一级缓存指的就是sqlsession,在sqlsession中有一个数据区域,是map结构,这个区域就是一级缓存区域。

    • 一级缓存中的key是由sql语句、条件、statement等信息组成一个唯一值。
    • 一级缓存中的value,就是查询出的结果对象。
  • 二级缓存指的就是同一个namespace下的mapper

    • 二级缓存中,也有一个map结构。具体的结构和一级缓存是一样的,key和value的结构都相同。
    • 但是生命周期比一级缓存的生命周期要长。

一级缓存是默认使用的。 二级缓存需要手动开启。

一级缓存 (sqlsession缓存)

第一次查询会去缓存中去查,如果查不到,就查DB然后加入缓存。但是要是有增删改操作并且提交了,就会清空一级缓存。

一级缓存里面是一个hashmap:localCache 这个Map,key为 将Statement Id + Offset + Limmit + Sql + Params 等5个元素组合成一个CacheKey对象,并重写了他们的equals方法,通过这个对象作为缓存map的key。

【一级缓存有两个级别:SESSION 和 STATEMENT 默认是session的就是针对当前会话的。两个会话的缓存互不影响】

配置: <setting name="localCacheScope" value="SESSION"/>

存在问题

  • 脏读多个sqlsession的缓存数据不一致。

二级缓存(mapper缓存)

每一个mapper的缓存区域。同样增删改会去清空缓存。二级缓存开启后,同一个namespace下的所有操作语句,都影响着同一个Cache,被多个sqlsession共享。

当开启缓存后,数据的查询执行的流程就是 二级缓存 -> 一级缓存 -> 数据库。先去二级缓存里面查,然后没有才去一级缓存。

配置

  • 在mapper文件中配置<cached/>就是开启二级缓存。
  • <setting name="cacheEnabled" value="true"/>

存在问题

当sql语句是多表查询的时候,我改了另外一个namespce的表内容,那个namespce的表就无法感知了。那个namespace就是脏数据。

总结

mybatis的缓存机制最好全关了不要使用。

  • Mybatis本身是一个持久层框架,它不是专门的缓存框架,所以它对缓存的实现不够好,不能支持分布式。

  • 我们缓存可以再外面做,比如Ehcache是一个分布式的缓存框架。需要这个ehcache包,实现分布式缓存。其实我们可以在我们的代码层面来实现缓存。想实现自己的缓存只要实现Cache接口即可,然后配置mapper中的cache使用自己写的类。