缓存机制
基本概念
SqlSession
:
- 代表和数据库的一次会话,向用户提供了操作数据库的方法。
MappedStatement
:
- 代表要发往数据库执行的指令,可以理解为是
SQL
的抽象表示。
Executor
:
- 代表用来和数据库交互的执行器,接受
MappedStatment
作为参数。
NameSpace
:
- 每个
Mapper
文件只能配置一个NameSpace
,用来做Mapper
文件级别的缓存共享。
一级缓存
在一次
SqlSession
中(数据库会话),程序执行多次查询,且查询条件完全相同,多次查询之间程序没有其他增删改操作。
- 则第二次及后面的查询可以从缓存中获取数据,避免走数据库。
每个
SqlSession
中持有了Executor
,每个Executor
中有一个LocalCache
。当用户发起查询时,
MyBatis
根据当前执行的语句生成MappedStatement
。在
Local Cache
进行查询,如果缓存命中的话,直接返回结果给用户。
- 如果缓存没有命中的话,查询数据库,结果写入
Local Cache
,最后返回结果给用户。
一级缓存配置:
在
mybatis-config.xml
文件配置,name=localCacheScope
。
value
有两种值:SESSION
和STATEMENT
<configuration>
<settings>
<setting name="localCacheScope" value="SESSION"/>
</settings>
<configuration>
SESSION
:开启一级缓存功能
STATEMENT
:
- 缓存只对当前执行的这一个
SQL
语句有效,也就是没有用到一级缓存功能。
一级缓存失效的场景:
不同的
SqlSession
对应不同的一级缓存同一个
SqlSession
但是查询条件不同同一个
SqlSession
两次查询期间执行了任何一次增删改操作同一个
SqlSession
两次查询期间手动清空了缓存
二级缓存
相对于一级缓存来说,实现了SqlSession
之间缓存数据的共享,同时粒度更加的细,能够到NameSpace
级别。
通过
Cache
接口实现类不同的组合,对Cache
的可控性也更强。
一级缓存最大的共享范围就是一个 SqlSession
内部,如果多个 SqlSession
之间需要共享缓存,则需要使用到二级缓存。
开启二级缓存后,会使用
CachingExecutor
装饰Executor
,进入一级缓存的查询流程前。
- 先在
CachingExecutor
进行二级缓存的查询。同一个
NameSpace
下的所有操作语句,都影响着同一个Cache
。
每个 Mapper
文件只能配置一个 NameSpace
,用来做 Mapper
文件级别的缓存共享。
<mapper namespace="mapper.StudentMapper"></mapper>
二级缓存被同一个 NameSpace
下的多个 SqlSession
共享,是一个全局的变量。
MyBatis
的二级缓存不适应用于映射文件中存在多表查询的情况。由于
MyBatis
的二级缓存是基于NameSpace
的。
- 多表查询语句所在的
NameSpace
无法感应到其他NameSpace
中的语句对多表查询中涉及的表进行的修改,引发脏数据问题。
开启二级缓存需要在 mybatis-config.xml
中配置:
<settingname="cacheEnabled"value="true"/>
缓存查询的顺序
先查询二级缓存,因为二级缓存中可能会有其他程序已经查出来的数据,可以拿来直接使用
如果二级缓存没有命中,再查询一级缓存
如果一级缓存也没有命中,则查询数据库
SqlSession
关闭之后,一级缓存中的数据会写入二级缓存