36道MyBatis面試專題,offer在向你招手

1、什么是 MyBatis?

答:MyBatis 是一個可以自定義 SQL、存儲過程和高級映射的持久層框架。

2、講下 MyBatis 的緩存

答:MyBatis 的緩存分為一級緩存和二級緩存,一級緩存放在 session 里面,默認就有,二級緩
存放在它的命名空間里,默認是不打開的,使用二級緩存屬性類需要實現(xiàn) Serializable 序列化
接口(可用來保存對象的狀態(tài)),可在它的映射文件中配置<cache/>

3、Mybatis 是如何進行分頁的?分頁插件的原理是什么?

答:
1)Mybatis 使用 RowBounds 對象進行分頁,也可以直接編寫 sql 實現(xiàn)分頁,也可以使用
Mybatis 的分頁插件。
2)分頁插件的原理:實現(xiàn) Mybatis 提供的接口,實現(xiàn)自定義插件,在插件的攔截方法內(nèi)攔
截待執(zhí)行的 sql,然后重寫 sql。
舉例:select * from student,攔截 sql 后重寫為:select t.* from (select * from student)t
limit 0,10

4、簡述 Mybatis 的插件運行原理,以及如何編寫一個插件?

答:
1)Mybatis 僅可以編寫針對 ParameterHandler、ResultSetHandler、StatementHandler、
Executor 這 4 種接口的插件,Mybatis 通過動態(tài)代理,為需要攔截的接口生成代理對象以實
現(xiàn)接口方法攔截功能,每當執(zhí)行這 4 種接口對象的方法時,就會進入攔截方法,具體就是
InvocationHandler 的 invoke()方法,當然,只會攔截那些你指定需要攔截的方法。
2)實現(xiàn) Mybatis 的 Interceptor 接口并復寫 intercept()方法,然后在給插件編寫注解,指定
要攔截哪一個接口的哪些方法即可,記住,別忘了在配置文件中配置你編寫的插件。

5、Mybatis 動態(tài) sql 是做什么的?都有哪些動態(tài) sql?能簡述一下動態(tài) sql 的執(zhí)行原理不?

答:
1)Mybatis 動態(tài) sql 可以讓我們在 Xml 映射文件內(nèi),以標簽的形式編寫動態(tài) sql,完成邏輯
判斷和動態(tài)拼接 sql 的功能。
2)Mybatis 提供了 9 種動態(tài) sql 標簽:
trim|where|set|foreach|if|choose|when|otherwise|bind。 3)其執(zhí)行原理為,使用 OGNL 從 sql 參數(shù)對象中計算表達式的值,根據(jù)表達式的值動態(tài)拼
接 sql,以此來完成動態(tài) sql 的功能。

6、#{}和${}的區(qū)別是什么?

答:
1)#{}是預編譯處理,{}是字符串替換。 2)Mybatis 在處理#{}時,會將 sql 中的#{}替換為?號,調(diào)用 PreparedStatement 的 set 方法 來賦值; 3)Mybatis 在處理{}時,就是把${}替換成變量的值。
4)使用#{}可以有效的防止 SQL 注入,提高系統(tǒng)安全性。

7、為什么說 Mybatis 是半自動 ORM 映射工具?它與全自動的區(qū)別在哪里?

答:Hibernate 屬于全自動 ORM 映射工具,使用 Hibernate 查詢關聯(lián)對象或者關聯(lián)集合對象
時,可以根據(jù)對象關系模型直接獲取,所以它是全自動的。而 Mybatis 在查詢關聯(lián)對象或
關聯(lián)集合對象時,需要手動編寫 sql 來完成,所以,稱之為半自動 ORM 映射工具。

8、Mybatis 是否支持延遲加載?如果支持,它的實現(xiàn)原理是什么?

答:
1)Mybatis 僅支持 association 關聯(lián)對象和 collection 關聯(lián)集合對象的延遲加載,association
指的就是一對一,collection 指的就是一對多查詢。在 Mybatis 配置文件中,可以配置是否
啟用延遲加載 lazyLoadingEnabled=true|false。 2)它的原理是,使用 CGLIB 創(chuàng)建目標對象的代理對象,當調(diào)用目標方法時,進入攔截器方
法,比如調(diào)用 a.getB().getName(),攔截器 invoke()方法發(fā)現(xiàn) a.getB()是 null 值,那么就會單
獨發(fā)送事先保存好的查詢關聯(lián) B 對象的 sql,把 B 查詢上來,然后調(diào)用 a.setB(b),于是 a 的
對象 b 屬性就有值了,接著完成 a.getB().getName()方法的調(diào)用。這就是延遲加載的基本原
理。

9、MyBatis 與 Hibernate 有哪些不同?

答:
1)Mybatis 和 hibernate 不同,它不完全是一個 ORM 框架,因為 MyBatis 需要程序員自己
編寫 Sql 語句,不過 mybatis 可以通過 XML 或注解方式靈活配置要運行的 sql 語句,并將
java 對象和 sql 語句映射生成最終執(zhí)行的 sql,最后將 sql 執(zhí)行的結(jié)果再映射生成 java 對
象。
2)Mybatis 學習門檻低,簡單易學,程序員直接編寫原生態(tài) sql,可嚴格控制 sql 執(zhí)行性
能,靈活度高,非常適合對關系數(shù)據(jù)模型要求不高的軟件開發(fā),例如互聯(lián)網(wǎng)軟件、企業(yè)運
營類軟件等,因為這類軟件需求變化頻繁,一但需求變化要求成果輸出迅速。但是靈活的
前提是 mybatis 無法做到數(shù)據(jù)庫無關性,如果需要實現(xiàn)支持多種數(shù)據(jù)庫的軟件則需要自定
義多套 sql 映射文件,工作量大。
3)Hibernate 對象/關系映射能力強,數(shù)據(jù)庫無關性好,對于關系模型要求高的軟件(例如
需求固定的定制化軟件)如果用 hibernate 開發(fā)可以節(jié)省很多代碼,提高效率。但是
Hibernate 的缺點是學習門檻高,要精通門檻更高,而且怎么設計 O/R 映射,在性能和對象
模型之間如何權(quán)衡,以及怎樣用好 Hibernate 需要具有很強的經(jīng)驗和能力才行。
總之,按照用戶的需求在有限的資源環(huán)境下只要能做出維護性、擴展性良好的軟件架構(gòu)都
是好架構(gòu),所以框架只有適合才是最好。

10、MyBatis 的好處是什么?

答:
1)MyBatis 把 sql 語句從 Java 源程序中獨立出來,放在單獨的 XML 文件中編寫,給程序的
維護帶來了很大便利。
2)MyBatis 封裝了底層 JDBC API 的調(diào)用細節(jié),并能自動將結(jié)果集轉(zhuǎn)換成 Java Bean 對象,
大大簡化了 Java 數(shù)據(jù)庫編程的重復工作。
3)因為 MyBatis 需要程序員自己去編寫 sql 語句,程序員可以結(jié)合數(shù)據(jù)庫自身的特點靈活
控制 sql 語句,因此能夠?qū)崿F(xiàn)比 Hibernate 等全自動 orm 框架更高的查詢效率,能夠完成復
雜查詢。

11、簡述 Mybatis 的 Xml 映射文件和 Mybatis 內(nèi)部數(shù)據(jù)結(jié)構(gòu)之間的映射關系?

答:Mybatis 將所有 Xml 配置信息都封裝到 All-In-One 重量級對象 Configuration 內(nèi)部。在
Xml 映射文件中,<parameterMap>標簽會被解析為 ParameterMap 對象,其每個子元素會
被解析為 ParameterMapping 對象。<resultMap>標簽會被解析為 ResultMap 對象,其每個子
元素會被解析為 ResultMapping 對象。每一個<select>、<insert>、<update>、<delete>標簽
均會被解析為 MappedStatement 對象,標簽內(nèi)的 sql 會被解析為 BoundSql 對象。

12、什么是 MyBatis 的接口綁定,有什么好處?

答:接口映射就是在 MyBatis 中任意定義接口,然后把接口里面的方法和 SQL 語句綁定,我們
直接調(diào)用接口方法就可以,這樣比起原來了 SqlSession 提供的方法我們可以有更加靈活的選
擇和設置.

13、接口綁定有幾種實現(xiàn)方式,分別是怎么實現(xiàn)的?

答:接口綁定有兩種實現(xiàn)方式,一種是通過注解綁定,就是在接口的方法上面加上
@Select@Update 等注解里面包含 Sql 語句來綁定,另外一種就是通過 xml 里面寫 SQL 來綁
定,在這種情況下,要指定 xml 映射文件里面的 namespace 必須為接口的全路徑名.

14、什么情況下用注解綁定,什么情況下用 xml 綁定?

答:當 Sql 語句比較簡單時候,用注解綁定;當 SQL 語句比較復雜時候,用 xml 綁定,一般用
xml 綁定的比較多

15、MyBatis 實現(xiàn)一對一有幾種方式?具體怎么操作的?

答:有聯(lián)合查詢和嵌套查詢,聯(lián)合查詢是幾個表聯(lián)合查詢,只查詢一次,通過在 resultMap 里面
配置 association 節(jié)點配置一對一的類就可以完成;嵌套查詢是先查一個表,根據(jù)這個表里面
的結(jié)果的外鍵 id,去再另外一個表里面查詢數(shù)據(jù),也是通過 association 配置,但另外一個表的
查詢通過 select 屬性配置。

16、Mybatis 能執(zhí)行一對一、一對多的關聯(lián)查詢嗎?都有哪些實現(xiàn)方式,以及它們之間的區(qū)

別?
答:能,Mybatis 不僅可以執(zhí)行一對一、一對多的關聯(lián)查詢,還可以執(zhí)行多對一,多對多的
關聯(lián)查詢,多對一查詢,其實就是一對一查詢,只需要把 selectOne()修改為 selectList()即
可;多對多查詢,其實就是一對多查詢,只需要把 selectOne()修改為 selectList()即可。
關聯(lián)對象查詢,有兩種實現(xiàn)方式,一種是單獨發(fā)送一個 sql 去查詢關聯(lián)對象,賦給主對
象,然后返回主對象。另一種是使用嵌套查詢,嵌套查詢的含義為使用 join 查詢,一部分
列是 A 對象的屬性值,另外一部分列是關聯(lián)對象 B 的屬性值,好處是只發(fā)一個 sql 查詢,
就可以把主對象和其關聯(lián)對象查出來。

17、MyBatis 里面的動態(tài) Sql 是怎么設定的?用什么語法?

答:MyBatis 里面的動態(tài) Sql 一般是通過 if 節(jié)點來實現(xiàn),通過 OGNL 語法來實現(xiàn),但是如果要
寫的完整,必須配合 where,trim 節(jié)點,where 節(jié)點是判斷包含節(jié)點有內(nèi)容就插入 where,否則不
插入,trim 節(jié)點是用來判斷如果動態(tài)語句是以 and 或 or 開始,那么會自動把這個 and 或者 or
取掉。

18、Mybatis 是如何將 sql 執(zhí)行結(jié)果封裝為目標對象并返回的?都有哪些映射形式?

答:
第一種是使用<resultMap>標簽,逐一定義列名和對象屬性名之間的映射關系。
第二種是使用 sql 列的別名功能,將列別名書寫為對象屬性名,比如 T_NAME AS NAME,對
象屬性名一般是 name,小寫,但是列名不區(qū)分大小寫,Mybatis 會忽略列名大小寫,智能
找到與之對應對象屬性名,你甚至可以寫成 T_NAME AS NaMe,Mybatis 一樣可以正常工
作。
有了列名與屬性名的映射關系后,Mybatis 通過反射創(chuàng)建對象,同時使用反射給對象的屬性
逐一賦值并返回,那些找不到映射關系的屬性,是無法完成賦值的。

19、Xml 映射文件中,除了常見的 select|insert|updae|delete 標簽之外,還有哪些標簽?

答:還有很多其他的標簽,<resultMap>、<parameterMap>、<sql>、<include>、
<selectKey>,加上動態(tài) sql 的 9 個標簽,
trim|where|set|foreach|if|choose|when|otherwise|bind 等,其中<sql>為 sql 片段標簽,通
過<include>標簽引入 sql 片段,<selectKey>為不支持自增的主鍵生成策略標簽。

20、當實體類中的屬性名和表中的字段名不一樣,如果將查詢的結(jié)果封裝到指定 pojo?

答:
1)通過在查詢的 sql 語句中定義字段名的別名。
2)通過<resultMap>來映射字段名和實體類屬性名的一一對應的關系。

21、模糊查詢 like 語句該怎么寫

答:
1)在 java 中拼接通配符,通過#{}賦值
2)在 Sql 語句中拼接通配符 (不安全 會引起 Sql 注入)

22、通常一個 Xml 映射文件,都會寫一個 Dao 接口與之對應, Dao 的工作原理,是否可以重載?

答:不能重載,因為通過 Dao 尋找 Xml 對應的 sql 的時候全限名+方法名的保存和尋找策
略。接口工作原理為 jdk 動態(tài)代理原理,運行時會為 dao 生成 proxy,代理對象會攔截接口
方法,去執(zhí)行對應的 sql 返回數(shù)據(jù)。

23、Mybatis 映射文件中,如果 A 標簽通過 include 引用了 B 標簽的內(nèi)容,請問,B 標簽能否定義在 A 標簽的后面,還是說必須定義在 A 標簽的前面?

答:雖然 Mybatis 解析 Xml 映射文件是按照順序解析的,但是,被引用的 B 標簽依然可以
定義在任何地方,Mybatis 都可以正確識別。原理是,Mybatis 解析 A 標簽,發(fā)現(xiàn) A 標簽引
用了 B 標簽,但是 B 標簽尚未解析到,尚不存在,此時,Mybatis 會將 A 標簽標記為未解
析狀態(tài),然后繼續(xù)解析余下的標簽,包含 B 標簽,待所有標簽解析完畢,Mybatis 會重新
解析那些被標記為未解析的標簽,此時再解析 A 標簽時,B 標簽已經(jīng)存在,A 標簽也就可
以正常解析完成了。

24、Mybatis 的 Xml 映射文件中,不同的 Xml 映射文件,id 是否可以重復?

答:不同的 Xml 映射文件,如果配置了 namespace,那么 id 可以重復;如果沒有配置
namespace,那么 id 不能重復;畢竟 namespace 不是必須的,只是最佳實踐而已。原因就
是 namespace+id 是作為 Map<String, MappedStatement>的 key 使用的,如果沒有
namespace,就剩下 id,那么,id 重復會導致數(shù)據(jù)互相覆蓋。有了 namespace,自然 id 就
可以重復,namespace 不同,namespace+id 自然也就不同。

25、Mybatis 中如何執(zhí)行批處理?

答:使用 BatchExecutor 完成批處理。

26、Mybatis 都有哪些 Executor 執(zhí)行器?它們之間的區(qū)別是什么?

答:Mybatis 有三種基本的 Executor 執(zhí)行器,SimpleExecutor、ReuseExecutor、
BatchExecutor。
1)SimpleExecutor:每執(zhí)行一次 update 或 select,就開啟一個 Statement 對
象,用完立刻關閉 Statement 對象。
2)ReuseExecutor:執(zhí)行 update 或 select,以 sql 作為
key 查找 Statement 對象,存在就使用,不存在就創(chuàng)建,用完后,不關閉 Statement 對象,
而是放置于 Map3)BatchExecutor:完成批處理。

27、Mybatis 中如何指定使用哪一種 Executor 執(zhí)行器?

答:在 Mybatis 配置文件中,可以指定默認的 ExecutorType 執(zhí)行器類型,也可以手動給
DefaultSqlSessionFactory 的創(chuàng)建 SqlSession 的方法傳遞 ExecutorType 類型參數(shù)。

28、Mybatis 執(zhí)行批量插入,能返回數(shù)據(jù)庫主鍵列表嗎?

答:能,JDBC 都能,Mybatis 當然也能。

29、Mybatis 是否可以映射 Enum 枚舉類?

答:Mybatis 可以映射枚舉類,不單可以映射枚舉類,Mybatis 可以映射任何對象到表的一
列上。映射方式為自定義一個 TypeHandler,實現(xiàn) TypeHandler 的 setParameter()和
getResult()接口方法。TypeHandler 有兩個作用,一是完成從 javaType 至 jdbcType 的轉(zhuǎn)換,
二是完成 jdbcType 至 javaType 的轉(zhuǎn)換,體現(xiàn)為 setParameter()和 getResult()兩個方法,分別
代表設置 sql 問號占位符參數(shù)和獲取列查詢結(jié)果。

30、如何獲取自動生成的(主)鍵值?

答:配置文件設置 usegeneratedkeys 為 true

31、在 mapper 中如何傳遞多個參數(shù)?

答:
1)直接在方法中傳遞參數(shù),xml 文件用#{0} #{1}來獲取
2)使用 @param 注解:這樣可以直接在 xml 文件中通過#{name}來獲取

32、resultType resultMap 的區(qū)別?

答:
1)類的名字和數(shù)據(jù)庫相同時,可以直接設置 resultType 參數(shù)為 Pojo 類
2)若不同,需要設置 resultMap 將結(jié)果名字和 Pojo 名字進行轉(zhuǎn)換

33、使用 MyBatis 的 mapper 接口調(diào)用時有哪些要求?

答:
1)Mapper 接口方法名和 mapper.xml 中定義的每個 sql 的 id 相同
2)Mapper 接口方法的輸入?yún)?shù)類型和 mapper.xml 中定義的每個 sql 的 parameterType 的
類型相同
3)Mapper 接口方法的輸出參數(shù)類型和 mapper.xml 中定義的每個 sql 的 resultType 的類型
相同
4)Mapper.xml 文件中的 namespace 即是 mapper 接口的類路徑。

34、Mybatis 比 IBatis 比較大的幾個改進是什么?

答:
1)有接口綁定,包括注解綁定 sql 和 xml 綁定 Sql
2)動態(tài) sql 由原來的節(jié)點配置變成 OGNL 表達式
3) 在一對一,一對多的時候引進了
association,在一對多的時候引入了 collection 節(jié)點,不過都是在 resultMap 里面配置

35、IBatis 和 MyBatis 在核心處理類分別叫什么?

答:IBatis 里面的核心處理類交 SqlMapClient,MyBatis 里面的核心處理類叫做 SqlSession。

36、IBatis 和 MyBatis 在細節(jié)上的不同有哪些?

答:
1)在 sql 里面變量命名有原來的#變量# 變成了#{變量}
2)原來的變量變成了${變量}
3)原來在 sql 節(jié)點里面的 class 都換名字交 type
4)原來的 queryForObject queryForList 變成了 selectOne selectList5)原來的別名設置在映
射文件里面放在了核心配置文件里

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容