1、談談你對 MyBatis 的理解?
- Mybatis是一個半ORM(對象關係映射)框架,它內部封裝了 JDBC,開發時只需要關注 SQL 語句本身,不需要花費精力去處理加載驅動、創建連接、創建 Statement 等繁雜的過程。程序員直接編寫原生態 SQL,可以嚴格控制 SQL 執行性能,靈活度高。
- MyBatis 可以使用 XML 或註解來配置和映射原生信息,將 POJO 映射成數據庫中的記錄,避免了幾乎所有的 JDBC 代碼和手動設置參數以及獲取結果集。
- 通過 XML 文件或註解的方式將要執行的各種 Statement 配置起來,並通過 Java 對象和 Statement 中 SQL 的動態參數進行映射生成最終執行的 SQL 語句,最後由 MyBatis 框架執行 SQL並將結果映射爲 Java 對象並返回。(從執行 SQL到返回 Result 的過程)。
2、MyBaits 的優缺點有哪些?
優點:
- 基於 SQL 語句編程,相當靈活,不會對應用程序或者數據庫的現有設計造成任何影響,SQL 寫在 XML 裏,解除 SQL 與程序代碼的耦合,便於統一管理;提供XML標籤,支持編寫動態 SQL 語句,並可重用;
- 與 JDBC 相比,減少了代碼量,消除了 JDBC 大量冗餘的代碼,不需要手動開關連接;
- 很好的與各種數據庫兼容(因爲 MyBatis 使用 JDBC 來連接數據庫,所以只要 JDBC 支持的數據庫 MyBatis 都支持);
- 提供映射標籤,支持對象與數據庫的 ORM 字段關係映射;提供對象關係映射標籤,支持對象關係組件維護。
缺點:
- SQL 語句的編寫工作量較大,尤其當字段多、關聯表多時,對開發人員編寫 SQL 語句的功底有一定要求;
- SQL 語句依賴於數據庫,導致數據庫移植性差,不能隨意更換數據庫。
3、MyBatis 與 Hibernate 有哪些不同?
- MyBatis 和 Hibernate不同,它不完全是一個 ORM 框架,因爲 MyBatis 需要程序員自己編寫 SQL 語句;Hibernate 對象/關係映射能力強,數據庫無關性好,對於關係模型要求高的軟件,如果用 Hibernate 開發可以節省很多代碼,提高效率;
- MyBatis 直接編寫原生態 SQL,可以嚴格控制 SQL 執行性能,靈活度高,非常適合對關係數據模型要求不高的軟件開發,因爲這類軟件需求變化頻繁,一但需求變化要求迅速輸出成果。但是靈活的前提是 MyBatis 無法做到數據庫無關性,如果需要實現支持多種數據庫的軟件,則需要自定義多套 SQL 映射文件,工作量大。
4、MyBatis 中 #{} 和 ${}的區別是什麼?
#{} 是預編譯處理,${} 是字符串替換
- Mybatis 在處理 #{} 時,會將 SQL 中的 #{} 替換爲 ? 號,調用 PreparedStatement 的 set 方法來賦值;使用 #{} 可以有效的防止 SQL 注入,提高系統安全性;
- MyBatis 在處理 ${} 時,就是把 ${} 替換成變量的值。
5、MyBatis 是如何進行分頁的?分頁插件的原理是什麼?
MyBatis 使用 RowBounds 對象進行分頁,它是針對 ResultSet 結果集執行的內存分頁,而非物理分頁。可以在 SQL 內直接書寫帶有物理分頁的參數來完成物理分頁功能,也可以使用分頁插件來完成物理分頁。
分頁插件的基本原理是使用 MyBatis 提供的插件接口,實現自定義插件,在插件的攔截方法內攔截待執行的 SQL,然後重寫 SQL,根據 dialect 方言,添加對應的物理分頁語句和物理分頁參數。
6、MyBatis 有幾種分頁方式?
- 數組分頁
- SQL 分頁
- 攔截器分頁
- RowBounds 分頁
7、MyBatis 邏輯分頁和物理分頁的區別是什麼?
- 物理分頁速度上並不一定快於邏輯分頁,邏輯分頁速度上也並不一定快於物理分頁。
- 物理分頁總是優於邏輯分頁:沒有必要將屬於數據庫端的壓力加到應用端來,就算速度上存在優勢,然而其它性能上的優點足以彌補這個缺點。
8、MyBatis 是否支持延遲加載?如果支持,它的實現原理是什麼?
Mybatis 僅支持 association 關聯對象和 collection 關聯集合對象的延遲加載,association 指的就是一對一,collection 指的就是一對多查詢。在MyBatis配置文件中,可以配置是否啓用延遲加載lazyLoadingEnabled=true|false。
它的原理是,使用 CGLIB 創建目標對象的代理對象,當調用目標方法時,進入攔截器方法,比如調用 a.getB().getName(),攔截器 invoke() 方法發現 a.getB() 是 null 值,那麼就會單獨發送事先保存好的查詢關聯 B 對象的 SQL,把 B 查詢上來,然後調用 a.setB(b),於是 a 的對象 b 屬性就有值了,接着完成 a.getB().getName() 方法的調用。這就是延遲加載的基本原理。
9、說一下 MyBatis 的一級緩存和二級緩存?
- 一級緩存:基於 PerpetualCache 的 HashMap 本地緩存,其存儲作用域爲 Session,當 Session flush 或 close 之後,該 Session 中的所有 Cache 就將清空,默認打開一級緩存;
- 二級緩存:與一級緩存其機制相同,默認也是採用 PerpetualCache,HashMap 存儲,不同在於其存儲作用域爲 Mapper(Namespace),並且可自定義存儲源,如 Ehcache。默認不打開二級緩存,要開啓二級緩存,使用二級緩存屬性類需要實現 Serializable 序列化接口(可用來保存對象的狀態),可在它的映射文件中配置 <cache/> ;
對於緩存數據更新機制,當某一個作用域(一級緩存 Session / 二級緩存 Namespaces)的進行了 C/U/D 操作後,默認該作用域下所有 select 中的緩存將被 clear。
10、Mybatis 有哪些執行器(Executor)?
Mybatis 有 3 種基本的執行器(Executor):
- SimpleExecutor:每執行一次 update 或 select,就開啓一個 Statement 對象,用完立刻關閉 Statement 對象;
- ReuseExecutor:執行 update 或 select,以 SQL 作爲 key 查找 Statement 對象,存在就使用,不存在就創建,用完後,不關閉 Statement 對象,而是放置於 Map 內,供下一次使用。簡言之,就是重複使用 Statement 對象;
- BatchExecutor:執行 update(沒有 select,JDBC 批處理不支持select),將所有 SQL 都添加到批處理中(addBatch()),等待統一執行(executeBatch()),它緩存了多個 Statement 對象,每個 Statement對 象都是 addBatch() 完畢後,等待逐一執行 executeBatch() 批處理。與 JDBC 批處理相同。
11、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 的功能。
12. MyBatis 只寫接口就能執行 SQL 的原因?
用過mybatis的小夥伴都能理解下面這段代碼,通過roleMapper這個接口直接從數據庫中拿到一個對象:
Role role = roleMapper.getRole(3L);
直覺告訴我們,一個接口是不能運行的啊,一定有接口的實現類,可是這個實現類我們自己沒寫啊,難道mybatis幫我們生成了?你猜的沒錯,mybatis利用動態代理幫我們生成了接口的實現類,這個類就是org.apache.ibatis.binding.MapperProxy,我先畫一下UML圖,MapperProxy就是下圖中的SubjectProxy類。