Mybatis執行流程
mybatis中xml解析是通過SqlSessionFactoryBuilder.build()方法。
初始化mybatis(解析xml文件構建成Configuration對象)並初始化SqlSessionFactory對象
-
- 在解析xml時會同時根據其中節點做相應的初始化操作
- 關鍵節點: settings、typeAliases、mappers
通過SqlSesssionFactory.openSession()方法打開一個SqlSession對象
-
- SqlSessionFactory對象的作用是里面存了全局的配置信息以及初始化環境和DataSource,DataSource對象可以用來開辟連接,SqlSessionFactory對象是用來保存全局信息並且打開數據庫連接
- 在打開SqlSession對象的時候就會開辟一個連接對象並傳給SqlSession對象,和數據庫打交道的操作入口在於SqlSession對象
通過SqlSession.getMapper()根據傳入的Mapper對象類型動態代理並返回一個動態代理后的Mapper對象
由SqlSession.select()/update(),MapperProxy對象的invoke()方法執行后再執行execure方法,再根據情況選擇執行select/update
Executor執行Query/queryFromDatabase,在前面經過參數名封裝和緩存查詢之后(緩存為空),會調用queryFromDatabase方法去數據庫當中查
SimpleExecurot執行doQuery()方法,初始化prepareStatement並且給#{}參數賦值
StatementHandler執行query()方法,執行sql語句
ResuletHandler.handleResultSets()方法封裝結果集
具體執行流程如下圖:
mybatis面試題
1. spring和mybatis整合之后為什么一級緩存會失效?
一級緩存使用者可以隨時使用或者銷毀緩存,從SqlSession對象打開時緩存就已經存在。當關閉SqlSession對象緩存就失效。
當與spring整合的時候,直接跳過SqlSession對象,無法直接操作到SqlSession對象,spring在操作SqlSession的時候,不知道用戶什么時候關閉,所以每調用完一個dao方法就關閉了,所以導致一級緩存失效。
如果開啟了事務,一級緩存就會生效,因為開啟了事務,執行完dao就不會銷毀,因為一旦銷毀,事務就沒有了,你開啟了事務,spring就知道你什么時候需要結束
2. 二級緩存中要注意的事情?
二級緩存里面的數據不能存放那種一直累加到很大的數據
二級緩存是基於命名空間的,當多個命名空間操作同一張表的時候,最好不要用二級緩存,當一個命名空間insert之的一,不會刷新緩存,用另一個命名空間select的時候還是會查詢緩存
3. ResultMap和ResultType的區別?
ResultMap是自己指定返回值與對象及與對象內部屬性名和數據庫列名的綁定
ResultType是直接返回值與別名庫當中的java對象的映射
4. #{}和${}的區別?
#{}將傳入的數據都當成一個字符串,會對自動傳的數據加一個雙引號,#{}方式能夠很大程度防止sql注入
${}將傳入的數據是直接顯示生成在sql中,${}無法防止sql注入
${}方式一般用於傳入數據庫對象,例如傳入表名
一般能用#{}的就別用${},Mybaits排序時使用order by動態參數時需要注意,用${}而不能用#{}
5. MyBatis與Hibernate有哪些不同?
MyBatis是一個半自動ORM而Hibernate是一個完全的ORM框架
因為MyBatis需要自己編寫sql語句,不過MyBatis可以通過xml或注解方式配置要運行的sql語句,並將java對象和sql語句映射生成最終執行的sql,最后將sql執行的結果再映射生成java對象。可嚴格控制sql執行性能,靈活度高。但是靈活的前提是 Mybatis無法做到數據庫無關性,如果需要實現支持多種數據庫的則需要自定義多套sql映射文件。
Hibernate對象/關系映射能力強,數據庫無關性好,對於關系模型要求高,如果用Hibernate開發可以節省很多代碼,提高效率。但是hibernate學習門檻高,要精通門檻更高,而且怎么設計O/R映射,在性能和對象模型之間如何權衡,以及怎樣用好Hibernate需要具有很強的經驗和能力。
6. 為什么說Mybatis是半自動ORM映射工具?它與全自動的區別在哪里?
Hibernate屬於全自動ORM映射工具,使用Hibernate查詢關聯對象或者關聯集合對象時,可以根據對象關系模型直接獲取,所以它是全自動的。
Mybatis在查詢關系或關聯集合對象時需要手動編寫sql來完成,所以稱之為半自動ORM映射工具。
7. Mybatis是如何進行分頁的?分頁插件的原理是什么?
Mybatis使用RowBounds對象進行分頁,它是釗對Resultset結果集執行的內存分頁,而非物理分頁,可以在sql內直接書寫帶有物理分頁的參數來完成物理分頁功能,也可以使用分頁插件來完成物理分頁。
分頁插件的基本原理是使用Mybatis提供的插件接口,實現自定義插件,在插件的攔截方法內攔截待執行的sql,然后重寫sql,根據dialect方言,添加對應的物理分頁語句和物理分頁參數。
8. Mybatis映射文件中,如果A標簽通過include引用B標簽的內容,請問B標簽能否定詢問在A標簽的后面,還是說必須定義在A標簽的前面?
雖然Mybatis解析xml映射文件是按照順序解析的,但是被引用的B標簽依然可以定義在任何地方,Mybatis都可以正常識別。原理是Mybatis解析A標簽時發現A標簽引用了B標簽,但是B標簽尚未解析到,此時,Mybatis會將A標簽標記為未解析狀態,然后繼續解析余下的標簽,包含B 標簽,待所有標簽解析完畢,Mybatis會重新解析那些被標記為未解析的標簽,此時再解析A標簽時,B標簽已經存在,A標簽就可以正常解析完成了。
9. Mybatis動態sql是做什么的?都有哪些動態sql?簡述一下動態sql的執行原理?
Mybatis動態sql可以讓我們在xml映射文件內,以標簽的形式編寫動態sql,完成邏輯判斷和動態拼接sql的功能。
Mybatis提供了9種動態sql標簽:trim、where、set、foreach、if、choose、when、otherwise、bind
執行原理:使用OGNL從sql參數對象中計算表達式的值,根據表達式的值動態拼接sql,以此來完成動態sql功能。