1、一级缓存
SqlSession级别的缓存,使用HashMap存储缓存数据,不同的SqlSession之间的缓存数据区域(HashMap)互不影响。
一级缓存的作用域是SqlSession范围(强调是不是同一个SqlSession),当在同一个SqlSession中执行两次相同的sql语句时,第一次执行完毕会将数据库中查询的数据写到缓存中,第二次查询时会从缓存中获取数据,不再去底层数据库查询(如下当DML操作又会重查)。
如果SqlSession执行DML操作(insert、delete、update),并commit提交到数据库,Mybatis则会清空SqlSession中的一级缓存,目的是刷新缓存。当SqlSession结束(调用SqlSessionclose()方法)后该SqlSession中的一级缓存也就不存在了。
Mybatis默认开启一级缓存,不需要进行任何设置。
2、二级缓存
mapper级别的缓存,二级缓存是多个SqlSession共享的。多个SqlSession使用同一个mapper的sql语句去操作数据库,得到的数据会存在二级缓存区域,同样使用的是HashMap进行数据存储。
mapper级别的缓存,其作用域是mapper的同一个namespace。不同的SqlSession执行同一个mapper下的namaspace的sql语句,且向sql中传递的参数也相同,第一次执行完会将数据写到缓存,第二次查询会从缓存中获取数据,不再去底层数据库查询。
mapper级别的缓存需要使用setting全局参数设置开启。配置方式如下:
<!-- 步骤1、Mybatis配置文件中开启二级缓存 -->
<settings>
<setting name="logImpl" value="LOG4J2"/>
<!-- 开启二级缓存 -->
<setting name="cacheEnabled" value="true"/>
</settings>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- 步骤2、mapper中开启二级缓存 -->
<mapper namespace="com.lfy.mapping.UserMapper">
<!-- 开启二级缓存
回收策略为先进先出
自动刷新时间60s
最多缓存512个引用对象
只读
-->
<cache
eviction="LRU"
flushInterval="60000"
size="512"
readOnly="true"/>
...
</mapper>
使用二级缓存,与查询结果映射的Java对象必须实现java.io.Serializable接口的序列化、反序列化操作,如果存在父类,其成员都需要实现序列化接口。实现序列化接口是为了对缓存数据进行序列化和反序列化操作,因为二级缓存数据存储介质多种多样,不一定在内存,有可能是硬盘或者远程服务器。
同一个SqlSession,多次执行同一个sql语句,会先查找一级缓存,如果没有,但开启了二级缓存功能,将会去二级缓存中查找。不同的SqlSession执行同一个namespace下的sql,只能去二级缓存查找先了。
select语句中使用“useCache=false”,则会禁用当前语句的二级缓存。select语句默认开启二级缓存。