mybatis提供了缓存机制, 有一级缓存, 二级缓存, 用于缓存查询结果. 默认情况下mybatis仅开启一级缓存的(springboot没有事务的情况下, 每个mapper操作语句都会重新生成一个SQLSession, 所以看不到一级缓存的效果. 开启事务就能看到缓存效果了), 要想使用二级缓存需要额外做配置. 配置二级缓存有两种方式, 第一种在mapper接口上添加@CacheNamespace注解, 第二种在mapper.xml文件中添加<cache />, 本文主要讲在mapper.xml文件中添加<cache />标签的方式.
添加<cache />标签后, 默认整个mapper中的select方法都会被缓存, 如果部分select方法不想使用缓存, 则可以在select标签上添加useCache="false"属性. 注意二级缓存的结果需要实现Serializable接口
代码如下:
<?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">
<mapper namespace="dictionaryMapper" >
<!-- 开启二级缓存 -->
<cache />
<select id="selectByDictNameAndParentType" resultType="dictionary">
select * from t_dictionary t
where t.dict_name=#{dictName,jdbcType=VARCHAR}
and t.parent_type=#{parentType,jdbcType=VARCHAR}
</select>
<select id="selectById" resultType="dictionary">
select * from t_dictionary t where t.id=#{id,jdbcType=BIGINT}
</select>
<!-- 不想使用缓存, 就添加useCache="false"属性,这样每次都是从数据库中查询 -->
<select id="selectByIdNonCache" resultType="dictionary" useCache="false">
select * from t_dictionary t where t.id=#{id,jdbcType=BIGINT}
</select>
</mapper>
开启了一二级缓存,执行mapper获取结果的步骤:
1. 先从二级缓存查询结果, 有就返回
2. 再从一级缓存查询结果, 有就返回
3. 从数据库冲查询结果, 并在事务提交之后将查询结果添加到二级缓存
***为什么提交后才将数据添加到二级缓存?
1. 一个事务中, 先更新数据,然后查询记录(此时尚未提交),之后逻辑异常导致事务回滚.
2. 如果将更新完数据后的查询结果直接添加到二级缓存,因事务回滚致使该缓存信息是错误的.
3. 在添加到二级缓存和事务回滚这段时间被其他线程拿到了这个错误的缓存信息, 会导致其他逻辑有误.
一级缓存命中的条件:
1. 同一会话(同一个sqlSession, 所以要开启事务)
2. 同一个mapper接口,相同的参数
3. 同一个mybatis环境(如: 一个使用生产环境, 一个使用开发环境配置文件)
二级缓存命中的条件:
1. 同一个mapper接口,相同的参数
2. 同一个mybatis环境(如: 一个使用生产环境, 一个使用开发环境配置文件)