史上最全Mybatis面試題

Mybatis面試題

一、什麼是Mybatis?

(1)Mybatis是一個半ORM(對象關係映射)框架,它內部封裝了JDBC,開發時只須要關注SQL語句自己,不須要花費精力去處理加載驅動、建立鏈接、建立statement等繁雜的過程。程序員直接編寫原生態sql,能夠嚴格控制sql執行性能,靈活度高。html

(2)MyBatis 可使用 XML 或註解來配置和映射原生信息,將 POJO映射成數據庫中的記錄,避免了幾乎全部的 JDBC 代碼和手動設置參數以及獲取結果集。java

(3)經過xml 文件或註解的方式將要執行的各類 statement 配置起來,並經過java對象和 statement中sql的動態參數進行映射生成最終執行的sql語句,最後由mybatis框架執行sql並將結果映射爲java對象並返回。(從執行sql到返回result的過程)。mysql

二、Mybaits的優勢:

(1)基於SQL語句編程,至關靈活,不會對應用程序或者數據庫的現有設計形成任何影響,SQL寫在XML裏,解除sql與程序代碼的耦合,便於統一管理;提供XML標籤,支持編寫動態SQL語句,並可重用。程序員

(2)與JDBC相比,減小了50%以上的代碼量,消除了JDBC大量冗餘的代碼,不須要手動開關鏈接;web

(3)很好的與各類數據庫兼容(由於MyBatis使用JDBC來鏈接數據庫,因此只要JDBC支持的數據庫MyBatis都支持)。面試

(4)可以與Spring很好的集成;spring

(5)提供映射標籤,支持對象與數據庫的ORM字段關係映射;提供對象關係映射標籤,支持對象關係組件維護。sql

三、MyBatis框架的缺點:

(1)SQL語句的編寫工做量較大,尤爲當字段多、關聯表多時,對開發人員編寫SQL語句的功底有必定要求。數據庫

(2)SQL語句依賴於數據庫,致使數據庫移植性差,不能隨意更換數據庫。編程

四、MyBatis框架適用場合:

(1)MyBatis專一於SQL自己,是一個足夠靈活的DAO層解決方案。

(2)對性能的要求很高,或者需求變化較多的項目,如互聯網項目,MyBatis將是不錯的選擇。

五、MyBatis與Hibernate有哪些不一樣?

(1)Mybatis和hibernate不一樣,它不徹底是一個ORM框架,由於MyBatis須要程序員本身編寫Sql語句。

(2)Mybatis直接編寫原生態sql,能夠嚴格控制sql執行性能,靈活度高,很是適合對關係數據模型要求不高的軟件開發,由於這類軟件需求變化頻繁,一但需求變化要求迅速輸出成果。可是靈活的前提是mybatis沒法作到數據庫無關性,若是須要實現支持多種數據庫的軟件,則須要自定義多套sql映射文件,工做量大。

(3)Hibernate對象/關係映射能力強,數據庫無關性好,對於關係模型要求高的軟件,若是用hibernate開發能夠節省不少代碼,提升效率。

六、#{}和${}的區別是什麼?

#{}是預編譯處理,${}是字符串替換。

Mybatis在處理#{}時,會將sql中的#{}替換爲?號,調用PreparedStatement的set方法來賦值;

Mybatis在處理 {}時,就是把 {}替換成變量的值。

使用#{}能夠有效的防止SQL注入,提升系統安全性。

``${}``是Properties文件中的變量佔位符,它能夠用於標籤屬性值和sql內部,屬於靜態文本
替換,好比${driver}會被靜態替換爲com.mysql.jdbc.Driver。

#{}是sql的參數佔位符,Mybatis會將sql中的#{}替換爲?號,在sql執行前會使用PreparedStatement的參數設置方法,
按序給sql的?號佔位符設置參數值,好比ps.setInt(0, parameterValue),#{item.name}的取值方式爲使用反射從參數對象中獲取item對象的name屬性值,
至關於param.getItem().getName()。
1. #將傳入的數據都當成一個字符串,會對自動傳入的數據加一個雙引號。如:order by #user_id#,若是傳入的值是111,那麼解析成sql時的值爲order by "111", 若是傳入的值是id,則解析成的sql爲order by "id".

2. $將傳入的數據直接顯示生成在sql中。如:order by $user_id$,若是傳入的值是111,那麼解析成sql時的值爲order by user_id, 若是傳入的值是id,則解析成的sql爲order by id.

3. #方式可以很大程度防止sql注入。 

4.$方式沒法防止Sql注入。

5.$方式通常用於傳入數據庫對象,例如傳入表名. 

6.通常能用#的就別用$.

MyBatis排序時使用order by 動態參數時須要注意,用$而不是#

字符串替換

默認狀況下,使用#{}格式的語法會致使MyBatis建立預處理語句屬性並以它爲背景設置安全的值(好比?)。這樣作很安全,很迅速也是首選作法,有時你只是想直接在SQL語句中插入一個不改變的字符串。好比,像ORDER BY,你能夠這樣來使用:

ORDER BY ${columnName}

這裏MyBatis不會修改或轉義字符串。

重要:接受從用戶輸出的內容並提供給語句中不變的字符串,這樣作是不安全的。這會致使潛在的SQL注入攻擊,所以你不該該容許用戶輸入這些字段,或者一般自行轉義並檢查。

七、當實體類中的屬性名和表中的字段名不同 ,怎麼辦 ?

第1種: 經過在查詢的sql語句中定義字段名的別名,讓字段名的別名和實體類的屬性名一致。

<select id=」selectorder」 parametertype=」int」 resultetype=」me.gacl.domain.order」>
    select order_id id, order_no orderno ,order_price price form orders where order_id=#{id};
</select>

第2種: 經過<resultMap>來映射字段名和實體類屬性名的一一對應的關係。

<select id="getOrder" parameterType="int" resultMap="orderresultmap">
        select * from orders where order_id=#{id}    
 </select>
 <resultMap type=」me.gacl.domain.order」 id=」orderresultmap」>
         <!–用id屬性來映射主鍵字段–>        
         <id property=」id」 column=」order_id」>         
         <!–用result屬性來映射非主鍵字段,property爲實體類屬性名,column爲數據表中的屬性–>        
         <result property = 「orderno」 column =」order_no」/>       
         <result property=」price」 column=」order_price」 />    
 </reslutMap>

八、 模糊查詢like語句該怎麼寫?

第1種:在Java代碼中添加sql通配符。

string wildcardname = 「%smi%」; 
list<name> names = mapper.selectlike(wildcardname);     
<select id=」selectlike」>
     select * from foo where bar like #{value}
</select>

第2種:在sql語句中拼接通配符,會引發sql注入

string wildcardname = 「smi」;
list<name> names = mapper.selectlike(wildcardname);
<select id=」selectlike」>
	select * from foo where bar like "%"${value}"%"   
</select>

九、一般一個Xml映射文件,都會寫一個Dao接口與之對應,請問,這個Dao接口的工做原理是什麼?Dao接口裏的方法,參數不一樣時,方法能重載嗎?

答:Dao接口即Mapper接口。接口的全限名,就是映射文件中的namespace的值;接口的方法名,就是映射文件中Mapper的Statement的id值;接口方法內的參數,就是傳遞給sql的參數。

Mapper接口是沒有實現類的,當調用接口方法時,接口全限名+方法名拼接字符串做爲key值,可惟必定位一個MapperStatement。在Mybatis中,每個<select>、<insert>、<update>、<delete>標籤,都會被解析爲一個MapperStatement對象。

舉例:com.mybatis3.mappers.StudentDao.findStudentById,
	能夠惟一找到namespace爲com.mybatis3.mappers.StudentDao下面 id 爲
	findStudentById 的 MapperStatement。

Mapper接口裏的方法,是不能重載的,由於是使用 全限名+方法名 的保存和尋找策略。Mapper 接口的工做原理是JDK動態代理,Mybatis運行時會使用JDK動態代理爲Mapper接口生成代理對象proxy,代理對象會攔截接口方法,轉而執行MapperStatement所表明的sql,而後將sql執行結果返回。

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

Mybatis使用RowBounds對象進行分頁,它是針對ResultSet結果集執行的內存分頁,而非物理分頁。能夠在sql內直接書寫帶有物理分頁的參數來完成物理分頁功能,也可使用分頁插件來完成物理分頁。

分頁插件的基本原理是使用Mybatis提供的插件接口,實現自定義插件,在插件的攔截方法內攔截待執行的sql,而後重寫sql,根據dialect方言,添加對應的物理分頁語句和物理分頁參數。

十一、Mybatis是如何將sql執行結果封裝爲目標對象並返回的?都有哪些映射形式?

第一種是使用<resultMap>標籤,逐必定義數據庫列名和對象屬性名之間的映射關係。

第二種是使用sql列的別名功能,將列的別名書寫爲對象屬性名。

有了列名與屬性名的映射關係後,Mybatis經過反射建立對象,同時使用反射給對象的屬性逐一賦值並返回,那些找不到映射關係的屬性,是沒法完成賦值的。

十二、如何執行批量插入?

首先,建立一個簡單的insert語句:

<insert id=」insertname」>
	insert into names (name) values (#{value})    
</insert>

而後在java代碼中像下面這樣執行批處理插入:

list<string> names = new arraylist(); 
names.add(「fred」);
names.add(「barney」);
names.add(「betty」);
names.add(「wilma」);
// 注意這裏 executortype.batch   
sqlsession sqlsession = sqlsessionfactory.opensession(executortype.batch);   
	 try {     
	 	namemapper mapper = sqlsession.getmapper(namemapper.class); 
	 	for (string name : names) {        
	 		mapper.insertname(name);     
	 		}     
	 		sqlsession.commit();    
	 	}catch(Exception e){     
	 		e.printStackTrace();     
	 		sqlSession.rollback();      
	 		throw e;     
	 		} finally {         
	 			sqlsession.close();    
	 			}

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

insert 方法老是返回一個int值 ,這個值表明的是插入的行數。

若是採用自增加策略,自動生成的鍵值在 insert 方法執行完後能夠被設置到傳入的參數對象中。

示例:

<insert id=」insertname」 usegeneratedkeys=」true」 keyproperty=」id」>     			  
	insert into names (name) values (#{name})
</insert>
name name = new name();
name.setname(「fred」); 
int rows = mapper.insertname(name);    // 完成後,id已經被設置到對象中
system.out.println(「rows inserted = 」 + rows);
system.out.println(「generated key value = 」 + name.getid());

1四、在mapper中如何傳遞多個參數?

(1)第一種:
//DAO層的函數
Public UserselectUser(String name,String area);  
//對應的xml,#{0}表明接收的是dao層中的第一個參數,#{1}表明dao層中第二參數,更多參數一致日後加便可。
<select id="selectUser"resultMap="BaseResultMap">
	select *  fromuser_user_t   whereuser_name = #{0} anduser_area=#{1}
</select>   
(2)第二種: 使用 @param 註解:
public interface usermapper {   
	user selectuser(@param(「username」) string username,@param(「hashedpassword」) string hashedpassword);
}
而後,就能夠在xml像下面這樣使用(推薦封裝爲一個map,做爲單個參數傳遞給mapper):
<select id=」selectuser」 resulttype=」user」>
	select id, username, hashedpassword from some_table where username = #{username} and hashedpassword = #{hashedpassword}
</select> 
(3)第三種:多個參數封裝成map
try{
	//映射文件的命名空間.SQL片斷的ID,就能夠調用對應的映射文件中的SQL
	//因爲咱們的參數超過了兩個,而方法中只有一個Object參數收集,所以咱們使用Map集合來裝載咱們的參數
	Map<String, Object> map = new HashMap();
     map.put("start", start);     
     map.put("end", end);     
     return sqlSession.selectList("StudentID.pagination", map); 
}catch(Exception e){     
     e.printStackTrace();     
     sqlSession.rollback();    
     throw e; 
}finally{ 
     MybatisUtil.closeSqlSession(); 
}

1五、Mybatis動態sql有什麼用?執行原理?有哪些動態sql?

Mybatis動態sql能夠在Xml映射文件內,以標籤的形式編寫動態sql,完成邏輯判斷並動態拼接sql的功能。

Mybatis提供了9種動態sql標籤:trim | where | set | foreach | if | choose | when | otherwise | bind。

其執行原理爲,使用OGNL從sql參數對象中計算表達式的值,根據表達式的值動態拼接sql,以此來完成動態sql的功能。

1六、Xml映射文件中,除了常見的select|insert|updae|delete標籤以外,還有哪些標籤?

答:<resultMap>、<parameterMap>、<sql>、<include>、<selectKey> ,加上動態sql的9個標籤,trim|where|set|foreach|if|choose|when|otherwise|bind等,其中爲sql片斷標籤,經過標籤引入sql片斷,爲不支持自增的主鍵生成策略標籤。

1七、Mybatis的Xml映射文件中,不一樣的Xml映射文件,id是否能夠重複?

不一樣的Xml映射文件,若是配置了namespace,那麼id能夠重複;若是沒有配置namespace,那麼id不能重複;

緣由就是namespace+id是做爲Map<String, MapperStatement>的key使用的,若是沒有namespace,就剩下id,那麼,id重複會致使數據互相覆蓋。有了namespace,天然id就能夠重複,namespace不一樣,namespace+id天然也就不一樣。

可是,在之前的Mybatis版本的namespace是可選的,不過新版本的namespace已是必須的了。

1八、爲何說Mybatis是半自動ORM映射工具?它與全自動的區別在哪裏?

Hibernate屬於全自動ORM映射工具,使用Hibernate查詢關聯對象或者關聯集合對象時,能夠根據對象關係模型直接獲取,因此它是全自動的。而Mybatis在查詢關聯對象或關聯集合對象時,須要手動編寫sql來完成,因此,稱之爲半自動ORM映射工具。

1九、 一對1、一對多的關聯查詢 ?

<mapper namespace="com.lcb.mapping.userMapper"> 
<!--association 一對一關聯查詢 -->
<select id="getClass" parameterType="int" resultMap="ClassesResultMap">
	select * from class c,teacher t where c.teacher_id=t.t_id and c.c_id=#{id}      
</select>       
<resultMap type="com.lcb.user.Classes" id="ClassesResultMap">
	<!-- 實體類的字段名和數據表的字段名映射 -->
	<id property="id" column="c_id"/>
	<result property="name" column="c_name"/>         
	<association property="teacher" javaType="com.lcb.user.Teacher"> 
	<id property="id" column="t_id"/>              
	<result property="name" column="t_name"/>          
	</association>      
</resultMap>        
<!--collection 一對多關聯查詢 -->      
<select id="getClass2" parameterType="int" resultMap="ClassesResultMap2">          
	select * from class c,teacher t,student s where c.teacher_id=t.t_id and c.c_id=s.class_id and c.c_id=#{id}      
</select>       
<resultMap type="com.lcb.user.Classes" id="ClassesResultMap2"> 
	<id property="id" column="c_id"/>          
	<result property="name" column="c_name"/>          
	<association property="teacher" javaType="com.lcb.user.Teacher">
	<id property="id" column="t_id"/>              
	<result property="name" column="t_name"/>          
	</association>           
	<collection property="student" ofType="com.lcb.user.Student"> 
	<id property="id" column="s_id"/>              
	<result property="name" column="s_name"/>          
	</collection>      
</resultMap>  
</mapper>

20、MyBatis實現一對一有幾種方式?具體怎麼操做的?

有聯合查詢和嵌套查詢,聯合查詢是幾個表聯合查詢,只查詢一次, 經過在resultMap裏面配置association節點配置一對一的類就能夠完成;

嵌套查詢是先查一個表,根據這個表裏面的結果的 外鍵id,去再另一個表裏面查詢數據,也是經過association配置,但另一個表的查詢經過select屬性配置。

2一、MyBatis實現一對多有幾種方式,怎麼操做的?

有聯合查詢和嵌套查詢。聯合查詢是幾個表聯合查詢,只查詢一次,經過在resultMap裏面的collection節點配置一對多的類就能夠完成;嵌套查詢是先查一個表,根據這個表裏面的 結果的外鍵id,去再另一個表裏面查詢數據,也是經過配置collection,但另一個表的查詢經過select節點配置。

2二、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()方法的調用。這就是延遲加載的基本原理。

固然了,不光是Mybatis,幾乎全部的包括Hibernate,支持延遲加載的原理都是同樣的。

2三、Mybatis的一級、二級緩存:

1)一級緩存: 基於 PerpetualCache 的 HashMap 本地緩存,其存儲做用域爲 Session,當 Session flush 或 close 以後,該 Session 中的全部 Cache 就將清空,默認打開一級緩存。

2)二級緩存與一級緩存其機制相同,默認也是採用 PerpetualCache,HashMap 存儲,不一樣在於其存儲做用域爲 Mapper(Namespace),而且可自定義存儲源,如 Ehcache。默認不打開二級緩存,要開啓二級緩存,使用二級緩存屬性類須要實現Serializable序列化接口(可用來保存對象的狀態),可在它的映射文件中配置 ;

3)對於緩存數據更新機制,當某一個做用域(一級緩存 Session/二級緩存Namespaces)的進行了C/U/D 操做後,默認該做用域下全部 select 中的緩存將被 clear 掉並從新更新,若是開啓了二級緩存,則只根據配置判斷是否刷新。

4)一級緩存演示&失效狀況 :同一次會話期間只要查詢過的數據都會保存在當 前SqlSession的一個Map中
• key:hashCode+查詢的SqlId+編寫的sql查詢語句+參數
• 一級緩存失效的四種狀況:
一、不一樣的SqlSession對應不一樣的一級緩存
二、同一個SqlSession可是查詢條件不一樣
三、同一個SqlSession兩次查詢期間執行了任何一次增 刪改操做
四、同一個SqlSession兩次查詢期間手動清空了緩存
二級緩存(second level cache),全局做用域緩存
二級緩存默認不開啓,須要手動配置,MyBatis提供二級緩存的接口以及實現,緩存實現要求 POJO實現Serializable接口 • 二級緩存在 SqlSession 關閉或提交以後纔會生效 •
使用步驟:
一、全局配置文件中開啓二級緩存
二、須要使用二級緩存的映射文件處使用cache配置緩存
三、注意:POJO須要實現Serializable接口
緩存相關屬性 • eviction=「FIFO」:緩存回收策略: • LRU – 最近最少使用的:移除最長時間不被使用的對象。 • FIFO – 先進先出:按對象進入緩存的順序來移除它們。 • SOFT – 軟引用:移除基於垃圾回收器狀態和軟引用規則的對象。 • WEAK – 弱引用:更積極地移除基於垃圾收集器狀態和弱引用規則的對象。 • 默認的是 LRU。 • flushInterval:刷新間隔,單位毫秒 • 默認狀況是不設置,也就是沒有刷新間隔,緩存僅僅調用語句時刷新 • size:引用數目,正整數 • 表明緩存最多能夠存儲多少個對象,太大容易致使內存溢出 • readOnly:只讀,true/false • true:只讀緩存;會給全部調用者返回緩存對象的相同實例。所以這些對象 不能被修改。這提供了很重要的性能優點。 • false:讀寫緩存;會返回緩存對象的拷貝(經過序列化)。這會慢一些, 可是安全,所以默認是 false。
緩存有關設置 • 一、全局setting的cacheEnable: – 配置二級緩存的開關。一級緩存一直是打開的。 • 二、select標籤的useCache屬性: – 配置這個select是否使用二級緩存。一級緩存一直是使用的 • 三、sql標籤的flushCache屬性: – 增刪改默認flushCache=true。sql執行之後,會同時清空一級和二級緩存。 查詢默認flushCache=false。 • 四、sqlSession.clearCache(): – 只是用來清除一級緩存。 • 五、當在某一個做用域 (一級緩存Session/二級緩存 Namespaces) 進行了 C/U/D 操做後,默認該做用域下所 有 select 中的緩存將被clear。
第三方緩存整合 • EhCache 是一個純Java的進程內緩存框架,具備快速、精 乾等特色,是Hibernate中默認的CacheProvider。 • MyBatis定義了Cache接口方便咱們進行自定義擴展。
• 步驟: – 一、導入ehcache包,以及整合包,日誌包 ehcache-core-2.6.8.jar、mybatis-ehcache-1.0.3.jar slf4j-api-1.6.1.jar、slf4j-log4j12-1.6.2.jar – 二、編寫ehcache.xml配置文件 – 三、配置cache標籤 – • 參照緩存:若想在命名空間中共享相同的緩存配置和實例。 可使用 cache-ref 元素來引用另一個緩存。

2四、什麼狀況下用註解綁定,什麼狀況下用xml綁定 ?

當Sql語句比較簡單時候,用註解綁定, 當SQL語句比較複雜時候,用xml綁定,通常用xml綁定的比較多。

2五、什麼是MyBatis的接口綁定?有哪些實現方式?

接口綁定,就是在MyBatis中任意定義接口,而後把接口裏面的方法和SQL語句綁定, 咱們直接調用接口方法就能夠,這樣比起原來了SqlSession提供的方法咱們能夠有更加靈活的選擇和設置。

接口綁定有兩種實現方式,一種是經過註解綁定,就是在接口的方法上面加上 @Select、@Update等註解,裏面包含Sql語句來綁定;另一種就是經過xml裏面寫SQL來綁定, 在這種狀況下,要指定xml映射文件裏面的namespace必須爲接口的全路徑名。當Sql語句比較簡單時候,用註解綁定, 當SQL語句比較複雜時候,用xml綁定,通常用xml綁定的比較多。

2六、使用MyBatis的mapper接口調用時有哪些要求?

① Mapper接口方法名和mapper.xml中定義的每一個sql的id相同;
② Mapper接口方法的輸入參數類型和mapper.xml中定義的每一個sql 的parameterType的類型相同;
③ Mapper接口方法的輸出參數類型和mapper.xml中定義的每一個sql的resultType的類型相同;
④ Mapper.xml文件中的namespace便是mapper接口的類路徑。

2七、Mapper編寫有哪幾種方式?

第一種:接口實現類繼承SqlSessionDaoSupport:使用此種方法須要編寫mapper接口,mapper接口實現類、mapper.xml文件。
(1)在sqlMapConfig.xml中配置mapper.xml的位置
<mappers>
    <mapper resource="mapper.xml文件的地址" />
    <mapper resource="mapper.xml文件的地址" />
</mappers>
(2)定義mapper接口
(3)實現類集成SqlSessionDaoSupport
mapper方法中能夠this.getSqlSession()進行數據增刪改查。
(4)spring 配置
<bean id=" " class="mapper接口的實現">
    <property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
</bean>

 第二種:使用org.mybatis.spring.mapper.MapperFactoryBean:
(1)在sqlMapConfig.xml中配置mapper.xml的位置,若是mapper.xml和mappre接口的名稱相同且在同一個目錄,這裏能夠不用配置
<mappers>
    <mapper resource="mapper.xml文件的地址" />
    <mapper resource="mapper.xml文件的地址" />
</mappers>
(2)定義mapper接口:
①mapper.xml中的namespace爲mapper接口的地址
②mapper接口中的方法名和mapper.xml中的定義的statement的id保持一致
③Spring中定義
<bean id="" class="org.mybatis.spring.mapper.MapperFactoryBean">
    <property name="mapperInterface"   value="mapper接口地址" /> 
    <property name="sqlSessionFactory" ref="sqlSessionFactory" /> 
</bean>

第三種:使用mapper掃描器:
(1)mapper.xml文件編寫:
mapper.xml中的namespace爲mapper接口的地址;
mapper接口中的方法名和mapper.xml中的定義的statement的id保持一致;
若是將mapper.xml和mapper接口的名稱保持一致則不用在sqlMapConfig.xml中進行配置。 
(2)定義mapper接口:
注意mapper.xml的文件名和mapper的接口名稱保持一致,且放在同一個目錄
(3)配置mapper掃描器:
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="mapper接口包地址"></property>
    <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/> 
</bean>
(4)使用掃描器後從spring容器中獲取mapper的實現對象。

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

答:Mybatis僅能夠編寫針對ParameterHandler、ResultSetHandler、StatementHandler、Executor這4種接口的插件,Mybatis使用JDK的動態代理,爲須要攔截的接口生成代理對象以實現接口方法攔截功能,每當執行這4種接口對象的方法時,就會進入攔截方法,具體就是InvocationHandler的invoke()方法,固然,只會攔截那些你指定須要攔截的方法。

編寫插件:實現Mybatis的Interceptor接口並複寫intercept()方法,而後在給插件編寫註解,指定要攔截哪個接口的哪些方法便可,記住,別忘了在配置文件中配置你編寫的插件。

2九、mybatis運行原理(面試回答)

在 MyBatis 運行開始時須要先經過 Resources 加載全局配置文件.
下面 須要實例化 SqlSessionFactoryBuilder 構建器.
幫助 SqlSessionFactory 接 口實現類 DefaultSqlSessionFactory.
在實例化 DefaultSqlSessionFactory 以前須要先建立 XmlConfigBuilder 解析全局配置文件流,並把解析結果存放在 Configuration 中.
以後把 Configuratin 傳遞給 DefaultSqlSessionFactory.
到此 SqlSessionFactory 工 廠建立成功.
由 SqlSessionFactory 工廠建立 SqlSession. 每次建立 SqlSession 時,都須要由 TransactionFactory 建立 Transaction 對象,同時還須要建立 SqlSession 的執行器 Excutor,最後實例化 DefaultSqlSession,傳遞給 SqlSession 接口.
根據項目需求使用 SqlSession 接口中的 API 完成具體的事務操做.
若是事務執行失敗,須要進行 rollback 回滾事務. 若是事務執行成功提交給數據庫.
關閉 SqlSession 到此就是 MyBatis 的運行原理.(面試官說的.)

30、Mybatis都有哪些Executor執行器?它們之間的區別是什麼?

答:Mybatis有三種基本的Executor執行器,SimpleExecutor、ReuseExecutor、BatchExecutor。
SimpleExecutor:每執行一次update或select,就開啓一個Statement對象,用完馬上關閉Statement對象。
ReuseExecutor:執行update或select,以sql做爲key查找Statement對象,存在就使用,不存在就建立,用完後,不關閉Statement對象,而是放置於Map<String, Statement>內,供下一次使用。簡言之,就是重複使用Statement對象。
BatchExecutor:執行update(沒有select,JDBC批處理不支持select),將全部sql都添加到批處理中(addBatch()),等待統一執行(executeBatch()),它緩存了多個Statement對象,每一個Statement對象都是addBatch()完畢後,等待逐一執行executeBatch()批處理。與JDBC批處理相同。
做用範圍:Executor的這些特色,都嚴格限制在SqlSession生命週期範圍內。

3一、Mybatis中如何指定使用哪種Executor執行器?

答:在Mybatis配置文件中,能夠指定默認的ExecutorType執行器類型,也能夠手動給DefaultSqlSessionFactory的建立SqlSession的方法傳遞ExecutorType類型參數。
1五、Mybatis是否能夠映射Enum枚舉類?
答:Mybatis能夠映射枚舉類,不單能夠映射枚舉類,Mybatis能夠映射任何對象到表的一列上。映射方式爲自定義一個TypeHandler,實現TypeHandler的setParameter()和getResult()接口方法。TypeHandler有兩個做用,一是完成從javaType至jdbcType的轉換,二是完成jdbcType至javaType的轉換,體現爲setParameter()和getResult()兩個方法,分別表明設置sql問號佔位符參數和獲取列查詢結果。

3二、Mybatis映射文件中,若是A標籤經過include引用了B標籤的內容,請問,B標籤可否定義在A標籤的後面,仍是說必須定義在A標籤的前面?

答:雖然Mybatis解析Xml映射文件是按照順序解析的,可是,被引用的B標籤依然能夠定義在任何地方,Mybatis均可以正確識別。
原理是,Mybatis解析A標籤,發現A標籤引用了B標籤,可是B標籤還沒有解析到,尚不存在,此時,Mybatis會將A標籤標記爲未解析狀態,而後繼續解析餘下的標籤,包含B標籤,待全部標籤解析完畢,Mybatis會從新解析那些被標記爲未解析的標籤,此時再解析A標籤時,B標籤已經存在,A標籤也就能夠正常解析完成了。

3三、簡述Mybatis的Xml映射文件和Mybatis內部數據結構之間的映射關係?

答:Mybatis將全部Xml配置信息都封裝到All-In-One重量級對象Configuration內部。在Xml映射文件中,標籤會被解析爲ParameterMap對象,其每一個子元素會被解析爲ParameterMapping對象。標籤會被解析爲ResultMap對象,其每一個子元素會被解析爲ResultMapping對象。每個、、、標籤均會被解析爲MappedStatement對象,標籤內的sql會被解析爲BoundSql對象。

3四、Mybatis比IBatis比較大的幾個改進是什麼?

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

3五、IBatis和MyBatis在覈心處理類分別叫什麼?

IBatis裏面的核心處理類交SqlMapClient, MyBatis裏面的核心處理類叫作SqlSession

3六、IBatis和MyBatis在細節上的不一樣有哪些?

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

3七、Mybatis映射文件中,若是A標籤經過include引用了B標籤的內容,請問,B標籤可否定義在A標籤的後面,仍是說必須定義在A標籤的前面?

答:雖然Mybatis解析Xml映射文件是按照順序解析的,可是,被引用的B標籤依然能夠定義在任何地方,Mybatis均可以正確識別。原理是,Mybatis解析A標籤,發現A標籤引用了B標籤,可是B標籤還沒有解析到,尚不存在,此時,Mybatis會將A標籤標記爲未解析狀態,而後繼續解析餘下的標籤,包含B標籤,待全部標籤解析完畢,Mybatis會從新解析那些被標記爲未解析的標籤,此時再解析A標籤時,B標籤已經存在,A標籤也就能夠正常解析完成了。

3八、Mybatis的Xml映射文件中,不一樣的Xml映射文件,id是否能夠重複?

答:不一樣的Xml映射文件,若是配置了namespace,那麼id能夠重複;若是沒有配置namespace,那麼id不能重複;畢竟namespace不是必須的,只是最佳實踐而已。緣由就是namespace+id是做爲Map<String, MappedStatement>的key使用的,若是沒有namespace,就剩下id,那麼,id重複會致使數據互相覆蓋。有了namespace,天然id就能夠重複,namespace不一樣,namespace+id天然也就不一樣。