mybatis缓存
有一级缓存和二级缓存,关系可以通过下图理解
一级缓存
一级缓存数据结构
其他属性
- 简单来说,一级缓存是sqlSession级别的,二级缓存是mapper级别的
- 缓存的底层数据结构其实就是HashMap
- 一级缓存是默认开启的
- 查询顺序
- 先去缓存中查找数据
- 缓存中有就直接取数据返回
- 缓存中没有去数据库查。查到之后写入缓存中
- 如果对数据库进行了“增删改”操作,便会清空一级缓存
- 一级缓存也可以手动删除,sqlSession中的clearCache()方法,其实底层就是map.clear()方法实现的
- 一级缓存中的key值是在执行器执行sql语句是创建的,调用creatCacheKey方法
二级缓存
开启
- 二级缓存需要手工开启,需要在核心配置文件sqlMapConfig.xml中配置如下:
<!--开启二级缓存-->
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
并在mapper配置文件中加上cache标签
<cache></cache>
当使用注解开发时,用不到配置文件,则可以在mapper接口上添加@CacheNamespace注解开启二级缓存
其他属性
- 与一级缓存不同,二级缓存不是直接缓存的数据库查询结果封装成的对象,而是缓存的查询结果数据,并且存储介质多样,不一定只在内存中,还有可能在硬盘中,所以,需要缓存的pojo都要去实现序列化接口Serializable接口。
- 同样的,相同namespace中的任何一个mapper进行了增删改操作之后都会清空二级缓存
- mapper的xml配置文件中,可以给通过给sql语句配置useCache属性来控制该语句是否使用二级缓存,true(默认)为使用,false为不使用。通过注解开发时,可以给接口的查询方法挂上@Options注解,其中添加useCache属性完成。
xml配置方式举例:
<select id="findOrderAndUser1" resultMap="orderMap" useCache=false>
select * from orders o, user u where o.uid = u.id
</select>
注解方式:
@Options(useCache = false)
@Select("select * from user where id = #{id}")
public User findUserById(Integer id);
- 可以通过配置flushCache属性来控制sql语句是否更新二级缓存
xml方式
<select id="findOrderAndUser1" resultMap="orderMap" flushCache=false>
select * from orders o, user u where o.uid = u.id
</select>
注解方式
@Options(flushCache = false)
@Select("select * from user where id = #{id}")
public User findUserById(Integer id);
- 二级缓存的数据结构也是HashMap,实现二级缓存只需要实现mybatis的Cache接口,mybatis提供的默认实现类是
- 二级缓存不支持分布式缓存,只能在单台服务器上提供服务,可以结合redis实现分布式二级缓存,mybatis提供了针对redis实现二级缓存的实现,可以直接pom中引入即可。如下:
<dependency>
<groupId>org.mybatis.caches</groupId>
<artifactId>mybatis-redis</artifactId>
<version>1.0.0-beta2</version>
</dependency>