mapper.xml有一个命名空间 像这样

<select id="findUserByEntity" resultMap="UserResultMap" parameterType="com.ojama.business.entities.admin.User">
	select
	<include refid="Base_Column_List"/>
	from user s
	<where>
		<if test="createDate != null">
			and s.createDate=#{createDate}
		</if>
		<if test="name != null and name != ''">
			and s.name =#{name}
		</if>
		<if test="password !=null and password !=''">
			and s.password=#{password}
		</if>
		<choose>
			<when test="status !=null and status !=''">
				and s.status=#{status}
			</when>
			<otherwise>
				and s.status!=-1
			</otherwise>
		</choose>
	</where>
</select>


springboot mybatis 查询内容是否为null mybatis 查询过程_sql

这里输入 账号为admin 密码为123455

点击login

springboot mybatis 查询内容是否为null mybatis 查询过程_二级缓存_02

可以看到 首先 SqlSessionFactory会创建一个sqlsession

我们接着往下走 

springboot mybatis 查询内容是否为null mybatis 查询过程_sql_03

这里使用了代理 用sqlsession的selectList来替代了我们本身接口的实现

再往下走

springboot mybatis 查询内容是否为null mybatis 查询过程_sql_04

这里从hashMap中得到我们xml中配置的mapper信息,然后执行query

springboot mybatis 查询内容是否为null mybatis 查询过程_sql_05

这里判断xml中是否有<cache/>标签 如果有 cache对象不为空.

springboot mybatis 查询内容是否为null mybatis 查询过程_二级缓存_06

这里判断是否需要刷新缓存

这个缓存类本质是个hashMap.

springboot mybatis 查询内容是否为null mybatis 查询过程_缓存_07

因为这是第一次执行 缓存中没有值 接着往下走

springboot mybatis 查询内容是否为null mybatis 查询过程_缓存_08

这里还进行判断了一级缓存是否有值 如果有 从一级缓存开取.

当然 一级缓存也是一个hashMap

springboot mybatis 查询内容是否为null mybatis 查询过程_sql_09

springboot mybatis 查询内容是否为null mybatis 查询过程_缓存_10

接下来查询 执行doquery 进行真正的数据库查询

springboot mybatis 查询内容是否为null mybatis 查询过程_sql_11

 

springboot mybatis 查询内容是否为null mybatis 查询过程_二级缓存_12

可以发现 没找到 然后 本地缓存把值给删除了 最后把查出来的值放入了缓存中.

springboot mybatis 查询内容是否为null mybatis 查询过程_缓存_13

然后 二级缓存也把这次查询加入缓存.

最后 返回结果到service层.

springboot mybatis 查询内容是否为null mybatis 查询过程_缓存_14

我们再次进行查询 可以发现 同样的参数 可以在二级缓存中直接获取.

springboot mybatis 查询内容是否为null mybatis 查询过程_sql_15

这次输入密码为123456 二级缓存查询为空.

springboot mybatis 查询内容是否为null mybatis 查询过程_sql_16

然后 这次在本地缓存中 也没有找到.

springboot mybatis 查询内容是否为null mybatis 查询过程_二级缓存_17

这次依旧查询了数据库 把结果带入了缓存中.

这可以说明 缓存是根据命名空间 以及他的参数作为key值存储的.

springboot mybatis 查询内容是否为null mybatis 查询过程_缓存_18

二级缓存也放入了其中.

现在我们把xml的<cache/>进行删除

可以看到 缓存对象为空 二级缓存不再获取.

springboot mybatis 查询内容是否为null mybatis 查询过程_缓存_19

 

springboot mybatis 查询内容是否为null mybatis 查询过程_缓存_20

也同样的进行了查询数据库

springboot mybatis 查询内容是否为null mybatis 查询过程_缓存_21

并在最后放入了一级缓存中

springboot mybatis 查询内容是否为null mybatis 查询过程_二级缓存_22

但是 第二次参数相同时 并没有走一级缓存 直接获取刚刚查询过的list

springboot mybatis 查询内容是否为null mybatis 查询过程_缓存_23

而且我们可以发现

第一次localCache的hashcode为

springboot mybatis 查询内容是否为null mybatis 查询过程_缓存_24

第二次为

springboot mybatis 查询内容是否为null mybatis 查询过程_二级缓存_25

springboot mybatis 查询内容是否为null mybatis 查询过程_二级缓存_26

然后看了下构造函数.由上可知.本地缓存的作用域只存在于sqlsession会话中.

总结

每次线程进行一次查询 都会创建一个sqlsession对象,sqlsession对象会获取当前环境,然后创建出一个ChachingExecutor.然后sqlsession调用selectList方法. 从config中获取封装好的mapper对象 由executor进行查询.

Executor会先判断是否需要二级缓存 如果需要 判断该方法是否需要刷新缓存

然后从缓存中获取 如果缓存有值,则直接返回缓存对象.

如果没有 再从本地缓存中取 如果本地缓存也没有 直接查询数据库 并把结果放入一级缓存中.

然后 把结果放入二级缓存中 整个流程结束