关于mybatis的查询执行流程

mapper有一个命名空间 像这样

<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>

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

点击login

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

我们接着往下走 

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

再往下走

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

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

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

这个缓存类本质是个hashMap.

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

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

当然 一级缓存也是一个hashMap

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

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

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

最后 返回结果到service层.

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

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

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

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

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

二级缓存也放入了其中.

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

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

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

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

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

而且我们可以发现

第一次localCache的hashcode为

第二次为

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

写一个汇总吧.

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

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

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

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

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

猜你喜欢

转载自blog.csdn.net/jidong2622/article/details/82712010