Mybatis 查询缓存机制,根据缓存的作用域和声明周期,可以分为 一级缓存和二级缓存。
Mybatis 查询缓存的作用域是根据映射文件的namespace划分的,相同的namespace的mapper 查询数据放在同一个缓存区域。不同的namespace下的数据互不干扰,无论是一级缓存还是二级缓存都是按照namespace进行存放的。
一级,二级缓存的不同在于SqlSession一旦关闭,SqlSession的数据就不在存在了,一级缓存的数据也不在存在了,而二级缓存的而生命周期是存在于整个应用 ,于SqlSession的关闭无关,一级缓存存在于同一线程中,同一sqlSession 间的数据共享,二级缓存是跨线程的,不同SQLSession间的数据共享。
一级缓存-------从缓存中查找数据的依据
缓存的底层实现是Map ,Map的value 是查询结果
Map的key,即查询的依据使用的ORM架构不同,查询的依据也不相同
Mybatis的查询依据是:SQL的id + SQL语句
Hibernate的查询依据是:查询结果对象的id
增删改 对一级缓存的影响:增删改会清空一级缓存
内置二级缓存
由于Mybatis从缓存中读取数据的依据与SQL的id相关,而非查询出的对象。所以使用二级缓存的目的,不是在多个查询间共享查询结果
(所有查询的中只要结果存在该对象,就直接缓存中读取,这是对查询结果的共享。Hibernate中的缓存就是为了在多个查询间共享结果,但是Mybatis不是)
Mybatis是防止同一查询(相同的SQL+id)反复的执行。
mybatis缓存
1,一级缓存:基于 PerpetualCache的HashMap本地缓存,生命周期为session当Session falsh或close后,该session中的所有cache就将清空。
2,二级缓存和一级缓存的机制相同,默认也是采用 PerpetualCache的HashMap存储,不同在于存储作用域为Mapper(namespace),并且可自定义存储源,如Ehcache
3, 对于缓存数据更新机制,当某一个作用域(一级缓存session、二级缓存namespace )进行C/U/D操作后,默认该作用域下所有的select中的缓存将被清空。
一级缓存的作用域仅限于一个sqlsession,但是二级缓存的作用域是一个namespace。但并不是意味着同一个namespace创建的mapper可以互相读取缓存内容,这里的原则是,如果开启了二级缓存,那么在关闭sqlsession后,会把该sqlsession一级缓存中的数据添加到namespace的二级缓存中
即使开启了二级缓存,不同的sqlsession之间的缓存数据也不是想互访就能互访的,必须等到sqlsession关闭了以后,才会把其一级缓存中的数据写入二级缓存。
关闭刷新
在默认情况下,当sqlsession执行commit后会刷新缓存,但是也可以强制设置为不刷新,在不需要刷新的标签中加入
flushCache="false"
如
<select id="findUsers" resultType="cn.elinzhou.mybatisTest.pojo.User" flushCache="false">
那么,无论是否执行commit,缓存都不会刷新了。但是这样会造成脏读,只有在特殊情况下才使用
自动刷新
有些情况下,需要设置自动刷新缓存,那么需要配置对应mapper中的cache标签。
flushInterval="10000"
该属性表示每隔10秒钟自动刷新一遍缓存