1. 程式人生 > >Mybatis的常見面試題喊答案

Mybatis的常見面試題喊答案

簡介:

MyBatis是一個優秀的持久層ORM框架,它對jdbc的操作資料庫的過程進行封裝,使開發者只需要關注SQL 本身,而不需要花費精力去處理例如註冊驅動、建立connection、建立statement、手動設定引數、結果集檢索等jdbc繁雜的過程程式碼。

Mybatis通過xml或註解的方式將要執行的statement配置起來,並通過java物件和statement中的sql進行對映生成最終執行的sql語句,最後由mybatis框架執行sql並將結果對映成java物件並返回。

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

#{}是預編譯處理,${}是字串替換。
Mybatis在處理#{}時,會將sql中的#{}替換為?號,呼叫PreparedStatement的set方法來賦值;
Mybatis在處理${}時,就是把${}替換成變數的值。
使用#{}可以有效的防止SQL注入,提高系統安全性。

2、當實體類中的屬性名和表中的欄位名不一樣 ,怎麼辦 ?

第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>來對映欄位名和實體類屬性名的一一對應的關係 
1
 <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>

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

第1種:在Java程式碼中新增sql萬用字元。
1
 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>

4、通常一個Xml對映檔案,都會寫一個Dao介面與之對應,請問,這個Dao介面的工作原理是什麼?Dao接口裡的方法,引數不同時,方法能過載嗎?

Dao介面,就是人們常說的Mapper介面,介面的全限名,就是對映檔案中的namespace的值,介面的方法名,就是對映檔案中MappedStatement的id值,介面方法內的引數,就是傳遞給sql的引數。Mapper介面是沒有實現類的,當呼叫介面方法時,介面全限名+方法名拼接字串作為key值,可唯一定位一個MappedStatement,舉例:com.mybatis3.mappers.StudentDao.findStudentById,可以唯一找到namespace為com.mybatis3.mappers.StudentDao下面id = findStudentById的MappedStatement。在Mybatis中,每一個<select>、<insert>、<update>、<delete>標籤,都會被解析為一個MappedStatement物件。
Dao接口裡的方法,是不能過載的,因為是全限名+方法名的儲存和尋找策略。
Dao介面的工作原理是JDK動態代理,Mybatis執行時會使用JDK動態代理為Dao介面生成代理proxy物件,代理物件proxy會攔截介面方法,轉而執行MappedStatement所代表的sql,然後將sql執行結果返回。

5、Mybatis是如何進行分頁的?分頁外掛的原理是什麼?

Mybatis使用RowBounds物件進行分頁,它是針對ResultSet結果集執行的記憶體分頁,而非物理分頁,可以在sql內直接書寫帶有物理分頁的引數來完成物理分頁功能,也可以使用分頁外掛來完成物理分頁。
分頁外掛的基本原理是使用Mybatis提供的外掛介面,實現自定義外掛,在外掛的攔截方法內攔截待執行的sql,然後重寫sql,根據dialect方言,新增對應的物理分頁語句和物理分頁引數。

6、Mybatis是如何將sql執行結果封裝為目標物件並返回的?都有哪些對映形式?

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

7、如何執行批量插入?

首先,建立一個簡單的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(); 
 } finally { 
 sqlsession.close(); 
 }

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

insert 方法總是返回一個int值 - 這個值代表的是插入的行數。 
而自動生成的鍵值在 insert 方法執行完後可以被設定到傳入的引數物件中。 
示例: 
1
2
3
 <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());

9、在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 註解: 

 import org.apache.ibatis.annotations.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>
可以加一下我們的Java架構群:923888953
獲取往期高階架構資料、原始碼、筆記、視訊、
進群記得回覆一下接待你的老師、她會發你資料

10、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的功能。

11、Mybatis的Xml對映檔案中,不同的Xml對映檔案,id是否可以重複?

不同的Xml對映檔案,如果配置了namespace,那麼id可以重複;如果沒有配置namespace,那麼id不能重複;畢竟namespace不是必須的,只是最佳實踐而已。
原因就是namespace+id是作為Map<String, MappedStatement>的key使用的,如果沒有namespace,就剩下id,那麼,id重複會導致資料互相覆蓋。有了namespace,自然id就可以重複,namespace不同,namespace+id自然也就不同。

12、為什麼說Mybatis是半自動ORM對映工具?它與全自動的區別在哪裡?

Hibernate屬於全自動ORM對映工具,使用Hibernate查詢關聯物件或者關聯集合物件時,可以根據物件關係模型直接獲取,所以它是全自動的。而Mybatis在查詢關聯物件或關聯集合物件時,需要手動編寫sql來完成,所以,稱之為半自動ORM對映工具。

13、 一對一、一對多的關聯查詢 ?

<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> 

歡迎工作一到五年的Java工程師朋友們加入Java架構開發:760940986 群內提供免費的Java架構學習資料(裡面有高可用、高併發、高效能及分散式、Jvm效能調優、Spring原始碼,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多個知識點的架構資料)合理利用自己每一分每一秒的時間來學習提升自己,不要再用"沒有時間“來掩飾自己思想上的懶惰!趁年輕,使勁拼,給未來的自己一個交代!