mybatis_運行原理_查詢實現


mybatis接口是編程是利用jdk動態來實現的
1.代理對象無論執行哪一個方法都會執行mapperProxy的invoke方法,判斷當前執行器的方法是不是Object類的方法,由於代理對象的方法一部分是從須要代理的接口中實現過來的,另外一部分是Object裏面的方法好比equals、toString等方法。


2.接着將Method包裝成MapperMethod對象,該對象包含sqlCommand和MegthodSignature兩個對象,sqlCommand(在初始該對象傳入Configuration,接口的Class對象,Method進行初始化,調用自身的resolveMappedStatement方法獲取拼接statementId,即接口的全路徑名+方法名,調用Configuration.getMappedStatement方法獲取MappedStatement對象,該對象維護了一條<select|update|delete|insert>節點的封裝,這邊很容看出sqlCommand初始化傳入這三個參數的做用了,MegthodSignature存儲了當前要調用方法的詳細信息。

3.MapperMethod調用execute方法傳入sqlsession和方法參數,先經過sqlCommand判斷當前語句的類型。這裏咱們先講查詢返回對象的狀況,mybatis會經過MegthodSignature對象判斷當前要執行的方法返回的條數和類型,去執行相對應的方法。首先調用convertArgsToSqlCommandParam對當前執行的方法參數的解析,接着調用defaultSqlSession.selectOne(command.getName(), param)的方法。這裏的command.getName()的值是statementId也就是咱們開發配置的namespace加對應語句的id

接着調用this.selectList(statement, parameter)(這個this是defaultSqlSession)將查詢的數據返回第一條出去。

這裏來分析selectList方法,截圖以下:
首先經過statement,(其實就是咱們剛剛上面所說的statementId)從configuration獲取MappedStatement對象。MappedStatement包裝當前運行方法對應的sql語句以及其類型。接着調用executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER)
進一層包裝執行方法的參數,邏輯分頁對象以及MappedStatement對象。傳入該方法中,調用CachingExecutor這個執行器裏面query方法,判斷當前是否有配置緩存。沒有緩存默認調用SimpleExecutor裏面的query方法。繼續查看simpleExecutor.query方法,該方法會先從本地緩存中也就是一級緩存中查詢當前的要查詢的接口。mybatis通生成緩存key來惟一判斷當前的查詢是否和以前的查詢一致,一致則從緩存中取。(分析到這裏咱們能夠發現mybatis會先查二級緩存,再查一級緩存)。

若是一級緩存查詢爲空,則調用queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql)方法。會把查詢出來的結果放到一級緩存中。這裏 boundSql是封裝sql語句的詳細信息,rowBounds是mybatis邏輯分頁用的。parameter就是執行方法的參數。

進入doQuery方法,聲明原生jdbc的Statement 對象。獲取全局配置信息Configuration,new一個StatementHandler對,也就是mybatis的四大對象之一。

進去newStatementHandler方法,裏面有interceptorChain.pluginAll(statementHandler)這是mybatis在生成四大對象經過攔截器鏈去獲取代理對象,這邊不詳細解釋。會有專門一章來說。這裏生成的對象是PreparedStatementHandler (默認狀況)。

prepareStatement方法主要獲取connection,也就是數據庫鏈接對象。最終調用底層的數據查詢,並將查詢接口交給ResultSetHandler進行封裝。


sql

相關文章
相關標籤/搜索