1. 程式人生 > >mybatis面試題(二)

mybatis面試題(二)

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

不同的Xml對映檔案,如果配置了namespace,那麼id可以重複;如果沒有配置namespace,那麼id不能重複;畢竟namespace不是必須的,只是最佳實踐而已。

原因就是namespace+id是作為Map<String, MappedStatement>的key使用的,如果沒有namespace,就剩下id,那麼,id重複會導致資料互相覆蓋。

有了namespace,自然id就可以重複,namespace不同,namespace+id自然也就不同。

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

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

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

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

 

Xml對映檔案中,除了常見的select|insert|updae|delete標籤之外,還有哪些標籤?

注:這道題是京東面試題。

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

 

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

答:Mybatis使用RowBounds物件進行分頁,它是針對ResultSet結果集執行的記憶體分頁,而非物理分頁,可以在sql內直接書寫帶有物理分頁的引數來完成物理分頁功能,也可以使用分頁外掛來完成物理分頁。

分頁外掛的基本原理是使用Mybatis提供的外掛介面,實現自定義外掛,在外掛的攔截方法內攔截待執行的sql,然後重寫sql,根據dialect方言,新增對應的物理分頁語句和物理分頁引數。

舉例:select * from student,攔截sql後重寫為:select t.* from (select * from student)t limit 0,10

 

簡述Mybatis的外掛執行原理,以及如何編寫一個外掛。

Mybatis僅可以編寫針對ParameterHandler、ResultSetHandler、StatementHandler、Executor這4種介面的外掛,Mybatis使用JDK的動態代理,為需要攔截的介面生成代理物件以實現介面方法攔截功能,每當執行這4種介面物件的方法時,就會進入攔截方法,具體就是InvocationHandler的invoke()方法,當然,只會攔截那些你指定需要攔截的方法。

實現Mybatis的Interceptor介面並複寫intercept()方法,然後在給外掛編寫註解,指定要攔截哪一個介面的哪些方法即可,記住,別忘了在配置檔案中配置你編寫的外掛。

 

Mybatis執行批量插入,能返回資料庫主鍵列表嗎?

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

 

Mybatis能執行一對一、一對多的關聯查詢嗎?都有哪些實現方式,以及它們之間的區別。

能,Mybatis不僅可以執行一對一、一對多的關聯查詢,還可以執行多對一,多對多的關聯查詢,多對一查詢,其實就是一對一查詢,只需要把selectOne()修改為selectList()即可;

多對多查詢,其實就是一對多查詢,只需要把selectOne()修改為selectList()即可。

關聯物件查詢,有兩種實現方式,一種是單獨傳送一個sql去查詢關聯物件,賦給主物件,然後返回主物件。

另一種是使用巢狀查詢,巢狀查詢的含義為使用join查詢,一部分列是A物件的屬性值,另外一部分列是關聯物件B的屬性值,好處是隻發一個sql查詢,就可以把主物件和其關聯物件查出來。

那麼問題來了,join查詢出來100條記錄,如何確定主物件是5個,而不是100個?

其去重複的原理是<resultMap>標籤內的<id>子標籤,指定了唯一確定一條記錄的id列,Mybatis根據<id>列值來完成100條記錄的去重複功能,<id>可以有多個,代表了聯合主鍵的語意。

同樣主物件的關聯物件,也是根據這個原理去重複的,儘管一般情況下,只有主物件會有重複記錄,關聯物件一般不會重複。

舉例:下面join查詢出來6條記錄,一、二列是Teacher物件列,第三列為Student物件列,Mybatis去重複處理後,結果為1個老師6個學生,而不是6個老師6個學生。

       t_id    t_name           s_id

|          1 | teacher      |      38 |
|          1 | teacher      |      39 |
|          1 | teacher      |      40 |
|          1 | teacher      |      41 |
|          1 | teacher      |      42 |
|          1 | teacher      |      43 |

 

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,支援延遲載入的原理都是一樣的。

 

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

不同的Xml對映檔案,如果配置了namespace,那麼id可以重複;如果沒有配置namespace,那麼id不能重複;畢竟namespace不是必須的,只是最佳實踐而已。

原因就是namespace+id是作為Map<String, MappedStatement>的key使用的,如果沒有namespace,就剩下id,那麼,id重複會導致資料互相覆蓋。有了namespace,自然id就可以重複,namespace不同,namespace+id自然也就不同。

文章來源:https://mp.weixin.qq.com/s/Frk23f1M23OSCrotP8E00g