mybatis缓存机制
mybatis包含缓存机制,恶意方便的配置和定制。
默认定义了一级缓存和二级缓存。
- 默认情况下,只有一级缓存开启(sqlSession级别的缓存,也称本地缓存)
- 二级缓存需要手动开启和配置,是基于namespace级别的缓存(全局缓存)
- 为了提高扩展性。Mybatis定义了缓存接口Cache,可以通过实现Cache接口来自定义二级缓存
一级缓存
与数据库同义词会话期间查询到的数据会放在本地缓存中,以后获取相同的数据,只需要从缓存中取,没必要查数据库
一级缓存失效的情况
- sqlSession不同
- sqlSession相同,查询条件不同(此时该数据在一级缓存中还没有)
- sqlSession相同,但是在两次查询之间执行了增删改操作(这次增删改可能会对当前数据有影响)
- sqlSession相同,手动清除了一级缓存 session.clearCache()
二级缓存
一个namespace对应一个二级缓存,不同namespace查出的数据会放在不同的map中
开启二级缓存后,会使用CacheExecutor来装饰Executor,在查询数据时,先查询二级缓存,二级缓存没有再去查一级缓存
二级缓存的使用
开启全局二级缓存配置
1 | <settings> |
在映射文件中配置使用二级缓存
1 | <!-- |
由于可能会用到序列化和反序列化,所以使用缓存的对象要实现序列化接口(readOnly为false的时候需要用到序列化和反序列化)
否则会报java.io.NotSerializableException异常
注意:一定要在同一个sqlSessionFactory下的不同sqlSession下使用二级缓存,如果为不同的sqlSessionFactory,永远不可能命中二级缓存的(我测试的时候就犯糊涂了,找了半天配置的问题才反应过来)
1 |
|
二级缓存失效的情况
- 如果第一个sqlSession没有提交,第二个sqlSeesion是无法命中二级缓存中该数据的,(sqlSession提交的时候才会将数据存入到二级缓存)
- 两次查询之间包含了增删改操作(在增删改操作时默认会刷新缓存,导致缓存失效)
缓存相关配置总结
全局配置文件settings中配置 cacheEnabled=true 该配置只影响二级缓存,对于一级缓存没有影响
每个select标签都有useCache=”true” 默认为true,该配置只影响二级缓存,对于一级缓存没有影响
每个增删改标签都有flushCache=”true”,增删改操作执行后清除缓存,该清除会清除一级和二级缓存,默认true
如果在select上使用flushCache=”true”,则查询不会使用缓存,默认false
sqlSession.clearCache() 只是清除一级缓存,不会清除二级缓存
全局配置文件settings中配置localCacheScope 本地缓存作用域(只针对一级缓存),有两个取值SESSION|STATEMENT,默认是SESSION
可以使用STATEMENT来禁用一级缓存