這篇文章是緊接著上一篇 Mapper掃描載入和mapper介面代理的註冊 的,呼叫Mapper介面最終會回撥到MapperProxy的invoke方法。
可以看到的是呼叫執行前建立一個MapperMethod這個物件。然後呼叫cacehMapperMethod方法先快取這個mapperCache這個map快取中去,然後返回的MapperMethod, 最後執行它的execute方法。 從中看到execute方法,先判斷sqlcommand的操作型別,然後執行對應的case, 這裡選取SELECT且返回多個物件類別為例,進行一次資料的查詢過程呼叫的過程的分析。所以它會執行method.returnMany()這個分支,呼叫executeForMany這個方法, 首先,解析轉化引數為Map鍵值對的引數,如果沒有RowBoud這個引數,就直接執行sqlSession.selectList方法,這裡command的name就類全名+方法名,這裡的sqlSession是SqlSessionTemplate的例項,這個是在下面的這個程式碼注入的 接下來執行攔截器外掛,回撥下面這段程式碼它的SqlSessionIntercceptor的invoke方法, 執行完攔截器後,再接著呼叫DefaultSqlSession的selectList方法 從Configuration中獲取的MapperStatement這個物件,這個mapperStatement是在Mapper掃描的時候注入到Configureation中的,(這個回頭在補上這個分析),然後交給 Executor去執行,這裡看一下執行器的類,有執行器的策略,除錯是發現注入的是CacheExecutor這個例項,具體看一下query方法, 上面這段是DefaultSqlSession的query方法,mapperStqtement呼叫getBoundSql這個方法傳入引數物件返回一個BoundSql物件,這個物件是處理sql的類。 可以看出BoundSql是由sqlSource這個類,實際傳入的物件RawSqlSource這個類的例項,然後獲取引數對映,然後回到query方法繼續執行,建立快取的key,下面來建立快取的key。 可以看到快取的key的生成規則是:由MapperStatement的id,boundSql的偏移量、limit、sql以及引數值,hash= 37 * hashcode + basehashcode, CacheExecutor裡面委託一個SimpleExecutor執行,具體的CRUD操作,接著的執行SimpleExecutor的query方法, 這裡通過生成cacheKey獲取的Cache,這個Cache就是mybatis的二級快取,如果快取存在,先執行flushCache,如果有使用快取,則直接返回,如果cache是空的,則直接呼叫SimpleExecutor的query的方法,如下圖所示: 這個方法中首先是從二級快取中取,如果沒有,則執行queryFromDatabase方法從資料庫中查詢資料。如果有,則這屆從快取中取,還要處理當StatementType 是Callable的輸入引數9這裡呼叫資料庫的儲存過程的型別的配置),,當一次查詢的session的queryStach等於0,就是代表一次session資料庫的互動借宿,如果configuration配置的localCacheScope是LocalCacheScope.STATEMENT,則清除localCache的資料。 queryFromDataBase中首先先快取一個EXECUTION_PLACEHOLDER這個列舉值,接著執行SimpleExecutor的方法的doQuery方法,接著刪除localCache中的key, 這樣做主要是避免併發運算元據庫的時候,都去訪問資料庫。doQuery查詢完成後就去將資料快取到這個localCache中,最後一句是快取儲存過程的輸出引數的。暫時可以忽略,這裡暫時分析sql的執行。 doQuery方法首先是通過Configuration獲取建立一個StatementHandler,這裡建立的是PrepareStatementHandler,然後在執行statementHandler的query方法。 這列執行prepareStatementLogger執行execute方法,通過注入的DefaultResultSetHandler例項呼叫handlerResultSets方法轉換資料集,返回查詢的資料集。總結: 本篇文章主要介紹mapper的動態代理的呼叫過程,sqlsesionTemlate的執行select的處理過程,後面還有很多細節需要完善。