- MyBatis 的本地缓存 / 一级缓存 (local cache)是在会话(SqlSession)层面进行缓存的。
- 本地缓存 / 一级缓存 (local cache)在同一个会话(SqlSession)中共享,因为 SqlSession 的实例线程不是安全的,因此是本地缓存 / 一级缓存 (local cache)不能跨会话(SqlSession)共享,不同会话(SqlSession)之间相对独立
- MyBatis 在开启一个数据库会话时,会创建一个新的 SqlSession 对象,SqlSession 对象中会有一个新的Executor 对象,Executor 对象中持有一个新的 PerpetualCache 对象;
[ SqlSession——> ( Executor对象——> ( PerpetualCache对象 ) ) ]
- 当会话结束时,SqlSession 对象及其内部的 Executor 对象还有 PerpetualCache 对象也一并释放掉
注
- 一级缓存只在同一个sqlSession共享,当sqlSession不同时,缓存不会命中
- sqlSession 相同,只有查询条件完全相同缓存才会命中。因为条件不同,缓存中还没有数据。
- 由于不同会话(SqlSession)之间相对独立,对于相同的数据可能有不一样的缓存。因此在有多个会话或者分布式环境下,会存在脏数据的问题。
一级缓存的缓存级别
- MyBatis 的本地缓存 / 一级缓存 (local cache)是默认开启的,不需要任何的配置。
- 本地缓存 / 一级缓存 (local cache)无法关闭,但是有两种级别可选:
缓存级别 |
说明 |
session |
默认级别。在同一个 sqlSession 内,对同样的查询将不再查询数据库,直接从缓存中取出数据。 |
statement |
在同一个 statement 内,每次查询或着数据操作结束都会清掉一级缓存,可以避免不同的会话之间对于相同的数据可能有不一样的缓存而产生脏数据的问题。 |
- 切换缓存级别可以在 MyBatis 配置文件中添加以下代码:
<settings>
<setting name="localCacheScope" value="STATEMENT"/>
</settings>
<settings>
<setting name="localCacheScope" value="SESSION"/>
</settings>
清空一级缓存(生命周期)
- 默认当会话结束时,一级缓存会被全部清空。但是如果缓存过多的话,就会影响效率,因此就需要提前清空缓存
- 进行以下操作可以清空MyBatis一级缓存:
- SqlSession 调用 close() 方法,会释放掉一级缓存PerpetualCache对象,一级缓存将不可用
- SqlSession 调用 clearCache() 方法,会清空PerpetualCache对象中的数据,但是该对象仍可使用
- SqlSession 中执行任何一个数据的更新操作( update、delete、insert ) ,并且 commit(),都会清空 PerpetualCache 对象的数据,但是该对象可以继续使用
- 如果你想在特定的 SQL 语句改变默认的行为,只需要使用设置其 flushCache 即可,flushCache=true 时会同时清除一级缓存和二级缓存。比如,某些情况下你可能希望特定一条 select 语句清空缓存。
示例
<select ... flushCache="true"/>
<insert ... flushCache="true"/>
<update ... flushCache="true"/>
<delete ... flushCache="true"/>
- 清空一级缓存可能会导致性能下降,因为下一次查询需要重新从数据库中获取数据。因此,建议仅在必要时使用flushCache=true属性。