1. 程式人生 > >關於mybatis的查詢執行流程

關於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會先判斷是否需要二級快取 如果需要 判斷該方法是否需要重新整理快取

然後從快取中獲取 如果快取有值,則直接返回快取物件.

如果沒有 再從本地快取中取 如果本地快取也沒有 直接查詢資料庫 並把結果放入一級快取中.

然後 把結果放入二級快取中 整個流程結束