mybatis內置select


前面已經看過了內置的增刪改,這次來看下select的使用,如圖1:
圖1:

追着方法下去,最后能看到其實調用的是,selectList方法,如圖2:
圖2:

從圖2能看到,首先從Configuration中獲取到了statement,那看下在初始化的時候是怎么加載MappedStatement的,先會解析select|insert|update|delete如圖3:
圖3:

如圖4,會實例化一個XMLStatementBuilder,通過XMLStatementBuilder來生成MappedStatement
圖4:

parseStatementNode會解析4個標簽中的各種信息,如圖5
圖5:

最后會通過MapperBuilderAssistant,把MappedStatement放入到configuration的mappedStatements中去,如圖6
圖6:

在addMappedStatement方法中,通過MappedStatement.Builder構建MappedStatement,並放入到configuration中,如圖7
圖7:

那么在回過頭來繼續看select,在獲得MappedStatement后,會通過執行器執行query,看下query做了什么事情,如圖8:
圖8

在初始化的Executor是會變成CachingExecutor,還有一個Executor作為代理,如果不指定的話默認是SimpleExecutor
那么,會從MappedStatement中獲取BoundSql,如圖9:
圖9

BoundSql又是從SqlSource獲取,那就先來看下SqlSource吧,初始化階段,在解析select|insert|update|delete的時候,會生成一個SqlSource,如圖10:
圖10

LanguageDriver默認是XMLLanguageDriver,在Configuration實例化的時候已經加載好,這里就不展示了
那么來看下createSqlSource到底做了些什么,如圖11:
圖11

這里實例化了XMLScriptBuilder,如圖12:
圖12

這里就是所有的標簽如<if>、<foreach>等,都會放入nodeHandlerMap中,然后通過parseScriptNode方法解析,如圖13:
圖13:

在這里會判斷是否是動態sql還是靜態sql,動態sql就是包含有${}和<if>,那么來看下parseDynamicTags這個方法,如圖14:
圖14

這里就是解析${}和<if>等標簽,然后通過nodeHandlerMap獲取對應的NodeHandler,通過handler.handleNode(child, contents)來解析<if>,<foreach>等,如解析<where>如圖15,最后放到MixedSqlNode的List<SqlNode> contents中
圖15

如果有${}就是動態sql,會實例化DynamicSqlSource,不然就是實例化RawSqlSource
那么來看下RawSqlSource,DynamicSqlSource的話到后面才會解析,如圖16:
圖16

看下這里的getSql做了什么事情,如圖17:
圖17

實例化了DynamicContext,因為是靜態sql,所以不會有${}占位符,所以是StaticTextSqlNode,MixedSqlNode會去循環處理,如圖18,19:
圖18

圖19

DynamicContext中就已經有了一個普通的sql,就會去替換#{}的占位符,如圖20:
圖20

通過SqlSourceBuilder來解析#{},並替換成?,如圖21:
圖21

那在回過頭來看下SqlSource獲取BoundSql,因為前面看到是靜態sql,所以是RawSqlSource,但是在RawSqlSource有個sqlSource是StaticSqlSource,那么直接看StaticSqlSource中的getBoundSql方法,如圖22:
圖22

是直接實例化了一個BoundSql,把需要的一些信息都放在了BoundSql中
接着調用BaseExecutor中的query方法,如圖23:
圖23

重點看下queryFromDatabase這個方法,如圖24:
圖24

這里還封裝了一個doQuery方法,因為在初始化Executor的時候是CachingExecutor,在CachingExecutor又有一個代理,默認是SimpleExecutor,所以直接到SimpleExecutor查看doQuery方法,如圖25:
圖25

這里是會生成一個StatementHandler,通過StatementHandler會去實例化一個Statement,先看下configuration.newStatementHandler這個方法,如圖26:
圖26

這里實例化了一個RoutingStatementHandler,看下RoutingStatementHandler的構造函數,如圖27:
圖27

在這里又出現一個代理,在初始化的時候,會判斷是哪一種Statement,默認使用的是PREPARED,如圖28:
圖28

那繼續看下圖23中的prepareStatement方法,如圖29:
圖29

獲取連接,並設置時間和設置參數,先看下handler.prepare這個方法,如圖30:
圖30

主要做了三件事,設置prepareStatement,設置查詢超時時間,和fetchSize(mysql貌似不支持),主要看下設置prepareStatement,如圖31:
圖31

最后就是對應的?問號設置對應的值了,如圖32:
圖32

然后通過剛生成的PreparedStatement去查詢,如圖33:
圖33

在來看下動態sql是怎么解析的,和靜態的唯一區別就是在getBoundSql,如圖34:
圖34

在前面會解析到<if>等標簽和${},如果是碰到${},那么就是TextSqlNode,先來看下DynamicContext的構造函數,如圖35:
圖35

在來看下TextSqlNode是怎么解析的,如圖36:
圖36

能看到BindingTokenParser,那么看下BindingTokenParser具體是怎么解析${}占位符的,如圖37:
圖37

從DynamicContext中獲取剛剛放入的參數,通過Ognl來解析並賦值,解析的過程和靜態sql是一樣的,都是通過MixedSqlNode來循環解析,
解析完這些動態數據后,會把#{}替換成?,流程和靜態sql是一樣的。
 

接下來就要看下返回的數據是怎么處理的了,因為默認用PreparedStatementHandler,直接繼承了父類的構造函數,圖38
圖38
下面就是ResultSet后進行數據的轉換了,如圖39:
圖39
那么以上就是mybatis內置select了。下次來看下getMapper是怎么樣的。
如有不對請指出,共同提供,謝謝!!!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM