? ? 本文繼續沿用MyBatis系列 (1) ~ 啟動的demo,并在上文基礎上,說明MyBatis到底是如何執行sql的。MyBatis執行一個查詢方法,可以分為兩步:Session的創建和結果的獲取。本文的內容是基于demo特定代碼的結果,如果你的配置文件或測試代碼不一致,結果可能不一樣。
一、Session的創建
? ? 1.如測試代碼所示【測試代碼和demo詳見MyBatis系列 (1) ~ 啟動】,調用ssf.openSession方法(圖1),將會返回一個session對象。而openSession()調用openSessionFromDataSource方法(圖2),在openSessionFromDataSource方法(圖3)中configuration.newExecutor會生成一個Executor實例(圖4),而這個Executor對象則是一個CachingExecutor實例,包裝了SimpleExecutor實例(圖5),最后再利用Executor創建DefaultSqlSession實例并返回(圖3),至此session創建完成。session對于sql的執行,都是利用executor去完成,可以說Executor是seeeion最重要的對象。
二、結果的獲取
? ? 這個過程大概會經過MappedStatement查找、BoundSql的創建、CacheKey的創建、緩存查找、JDBC操作(數據庫Connection建立、Statement建立、參數設置、結果處理)、緩存更新這幾個步奏。其中緩存的部分以后再分析。
? ? 1.MappedStatement查找。從Configuration對象的mappedStatements根據id獲取。mappedStatement如何添加到mappedStatements可以參照MyBatis系列 (1) ~ 啟動。
? ? ? ? 2.BoundSql的創建。調用MappedStatement的getBoundSql方法會創建并返回一個BoundSql實例。BoundSql會封裝好sql、參數、類型、typeHandler等信息,具體過程如下所示。
? ? ? ? ? 3.CacheKey的創建。調用CachingExecutor的createCacheKey方法會返回一個CacheKey對象實例。CacheKey根據MappedStatement的id,偏移量,sql,參數,environment的id標識。如果他們都相等,則可以判斷CacheKey也相等。ddemo的CacheKey為"-1623403364:769426577:User.selectOneUser:0:2147483647:select t.id,t.name from user t where id = ?:2:development"。
? ? ? ? 4.JDBC操作。數據庫連接是在這里這里建立的,并不是一創建一個session實例就會建立一個連接。Connection由dataSource的doGetConnection方法返回。參數是由TypeHandler設置。
? ? ? ? 4.更新緩存。把相關結果存到localCache對象中,對于相同的CacheKey,如果緩存中有值,則不需要到數據庫去查詢。
? ? ? ? 最后把結果返回給調用者,至此,MyBatis查詢執行結束。