1. 程式人生 > >Mybatis#{}和${}的區別是什麼?,Xml對映檔案中,除了常見的select|insert|updae|delete標籤之外,還有哪些標籤?

Mybatis#{}和${}的區別是什麼?,Xml對映檔案中,除了常見的select|insert|updae|delete標籤之外,還有哪些標籤?

Mybatis技術內幕系列部落格,從原理和原始碼角度,介紹了其內部實現細節,無論是寫的好與不好,我確實是用心寫了,由於並不是介紹如何使用Mybatis的文章,所以,一些引數使用細節略掉了,我們的目標是介紹Mybatis的技術架構和重要組成部分,以及基本執行原理。

部落格寫的很辛苦,但是寫出來卻不一定好看,所謂開始很興奮,過程很痛苦,結束很遺憾。要求不高,只要讀者能從系列部落格中,學習到一點其他部落格所沒有的技術點,作為作者,我就很欣慰了,我也讀別人寫的部落格,通常對自己當前研究的技術,是很有幫助的。

儘管還有很多可寫的內容,但是,我認為再寫下去已經沒有意義,任何其他小的功能點,都是在已經介紹的基本框架和基本原理下執行的,只有結束,才能有新的開始。寫部落格也積攢了一些經驗,原始碼多了感覺就是複製黏貼,原始碼少了又覺得是空談原理,將來再寫部落格,我希望是“精煉博文”,好讀好懂美觀讀起來又不累,希望自己能再寫一部開源分散式框架原理系列部落格。

有膽就來,我出幾道Mybatis面試題,看你能回答上來幾道(都是我出的,可不是網上找的)。

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

注:這道題是面試官面試我同事的。

答:${}是Properties檔案中的變數佔位符,它可以用於標籤屬性值和sql內部,屬於靜態文字替換,比如${driver}會被靜態替換為com.mysql.jdbc.Driver。#{}是sql的引數佔位符,Mybatis會將sql中的#{}替換為?號,在sql執行前會使用PreparedStatement的引數設定方法,按序給sql的?號佔位符設定引數值,比如ps.setInt(0, parameterValue),#{item.name}的取值方式為使用反射從引數物件中獲取item物件的name屬性值,相當於param.getItem().getName()。

2、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>為不支援自增的主鍵生成策略標籤。

3、最佳實踐中,通常一個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執行結果返回。

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

注:我出的。

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

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

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

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

注:我出的。

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

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

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

注:我出的。

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

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

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

注:我出的。

答:第一種是使用<resultMap>標籤,逐一定義列名和物件屬性名之間的對映關係。第二種是使用sql列的別名功能,將列別名書寫為物件屬性名,比如T_NAME AS NAME,物件屬性名一般是name,小寫,但是列名不區分大小寫,Mybatis會忽略列名大小寫,智慧找到與之對應物件屬性名,你甚至可以寫成T_NAME AS NaMe,Mybatis一樣可以正常工作。

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

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

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

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中如何執行批處理?

注:我出的。

答:使用BatchExecutor完成批處理。

13、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生命週期範圍內。

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

注:我出的

答:在Mybatis配置檔案中,可以指定預設的ExecutorType執行器型別,也可以手動給DefaultSqlSessionFactory的建立SqlSession的方法傳遞ExecutorType型別引數。

15、Mybatis是否可以對映Enum列舉類?

注:我出的

答:Mybatis可以對映列舉類,不單可以對映列舉類,Mybatis可以對映任何物件到表的一列上。對映方式為自定義一個TypeHandler,實現TypeHandler的setParameter()和getResult()介面方法。TypeHandler有兩個作用,一是完成從javaType至jdbcType的轉換,二是完成jdbcType至javaType的轉換,體現為setParameter()和getResult()兩個方法,分別代表設定sql問號佔位符引數和獲取列查詢結果。

16、Mybatis對映檔案中,如果A標籤通過include引用了B標籤的內容,請問,B標籤能否定義在A標籤的後面,還是說必須定義在A標籤的前面?

注:我出的

答:雖然Mybatis解析Xml對映檔案是按照順序解析的,但是,被引用的B標籤依然可以定義在任何地方,Mybatis都可以正確識別。

原理是,Mybatis解析A標籤,發現A標籤引用了B標籤,但是B標籤尚未解析到,尚不存在,此時,Mybatis會將A標籤標記為未解析狀態,然後繼續解析餘下的標籤,包含B標籤,待所有標籤解析完畢,Mybatis會重新解析那些被標記為未解析的標籤,此時再解析A標籤時,B標籤已經存在,A標籤也就可以正常解析完成了。

17、簡述Mybatis的Xml對映檔案和Mybatis內部資料結構之間的對映關係?

注:我出的

答:Mybatis將所有Xml配置資訊都封裝到All-In-One重量級物件Configuration內部。在Xml對映檔案中,<parameterMap>標籤會被解析為ParameterMap物件,其每個子元素會被解析為ParameterMapping物件。<resultMap>標籤會被解析為ResultMap物件,其每個子元素會被解析為ResultMapping物件。每一個<select>、<insert>、<update>、<delete>標籤均會被解析為MappedStatement物件,標籤內的sql會被解析為BoundSql物件。

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

注:我出的

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

面試題看似都很簡單,但是想要能正確回答上來,必定是研究過原始碼且深入的人,而不是僅會使用的人或者用的很熟的人,以上所有面試題及其答案所涉及的內容,在我的Mybatis系列部落格中都有詳細講解和原理分析。

相關推薦

Mybatis#{}${}的區別是什麼?Xml對映檔案除了常見的select|insert|updae|delete標籤之外還有哪些標籤

Mybatis技術內幕系列部落格,從原理和原始碼角度,介紹了其內部實現細節,無論是寫的好與不好,我確實是用心寫了,由於並不是介紹如何使用Mybatis的文章,所以,一些引數使用細節略掉了,我們的目標是介紹Mybatis的技術架構和重要組成部分,以及基本執行原理。 部落格寫的

Mybatis 逆向工程生成mapper.xml 對映檔案方法的使用

方法1:selectByExample(TbItemDescExample  example)                     返回值:List<TbItemDesc>             作用:通過特定限制條件查詢資訊,example用於生成

mybatisXML對映檔案的函式-mybatis(1)

前言 由mybatis的逆向程式碼生成器生成的6個基本函式在日常開發中是有些力不從心的,我們可以寫寫自定義函式,去完成一些複雜的操作。 正文 繼續以之前建立的springboot專案為基礎,來學習mybatis的xml對映檔案的寫法,主要寫一下我用到比較多的一些

mybatis 對映檔案if標籤判斷字串相等

mybatis 對映檔案中,if標籤判斷字串相等,兩種方式: 因為mybatis對映檔案,是使用的ognl表示式,所以在判斷字串sex變數是否是字串Y的時候, <if test="sex=='Y'.toString()"> <if test = 'sex== "Y"'&g

mybatis***Mapper.xml對映檔案的配置細節

mapper對映檔案9大元素 對映檔案是以<mapper>作為根節點,在根節點中支援9個元素,分別為 insert、update、delete、select(增刪改查); cache、cache-ref、resultMap、parameterMap、sql。 例子:

mybatisxml對映檔案dao介面類entity實體類

xml對映檔案的標頭檔案: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis

MyBatis對映檔案註解的關係查詢(一對一一對多多對多)

對映關係的查詢 一對一查詢:(案例--人和卡) User實體類 package com.entity; public class User { private int uid;

mybatis學習筆記之——mybatis的Mapper XML對映檔案配置資訊

sql對映檔案對應的增刪改查都有自己的標籤: <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

Maven專案不打包 *.hbm.xml 對映檔案

今天做個maven專案,各種百度,終於解決了為什麼hbm.xml找不到,路徑都正確 話不多說。首先可以在pom.xml中配置 <build> <sourceDirectory>src/main/java</sourceDirectory>&nbs

mybatis的mapper對映檔案insert的用法

insert元素,這個標籤還有如下屬性: 1,id:名稱空間中的唯一標誌符,可用來代表這個語句。 2,parameterType:即將傳入的語句引數的完全限定類名或者別名 3,flushCash:預設值為true,任何時候只要語句被呼叫都會清空一級快取和二級快取。 4,stateme

關於mybatis傳入引數在相應對映檔案 Collection,List,Map,Set,@Param這幾種的混合傳入的獲取

本片文章還是基於mybatis的介面的方式(動態代理)來說明: 關於普通多值傳入的方式以及獲取方式連結:點選這裡   第一種既有註解,又有普通引數 有註解的可以使用註解使使用的名字,沒有註解的只能使用該引數對應的Key(param1或者其它位置) 示例

mybatis Mapper XML 對映檔案

傳送門:mybatis官方文件 Mapper XML 檔案詳解 1. select <select id="selectPerson" parameterType="int" parameterMap="deprecated" resultType="hashmap"

Mybatis xml對映檔案錯誤,導致Tomcat無法啟動,也不報異常

在做的專案,有時候tomcat啟動會陷入死迴圈,一直在啟動中,無法結束,自然也不會報異常. 查了一下網上的資料,需要自己重寫一下SqlSessionFactoryBean中的buildSqlSessionFactory方法,並替換原有的SqlSessionFactoryBean import

mybatis xml對映檔案找不到

問題: mybatis的xml對映檔案找不到。 原因: mapper.xml檔案在java目錄 <resources> <resource> <!--此處配置到j

mybatis系列之XML對映檔案

一、XML對映檔案 1.1 Mybatis的增刪改操作 mybatis允許增刪改直接定義以下型別返回值 Integer、Long、Boolean、void 1.2 sqlsession sqlSessionFactory.openSession(); 獲取的

Mybatis配置對映檔案parameterType的用法

在mybatis對映介面的配置中,有select,insert,update,delete等元素都提到了 parameterType的用法,parameterType為輸入引數,在配置的時候,配置相應的 輸入引數型別即可。parameterType有基本資料型別和複雜的資料型別配置。 1.基

Mybatis學習--Mapper.xml對映檔案

簡介 Mapper.xml對映檔案中定義了操作資料庫的sql,每個sql是一個statement,對映檔案是mybatis的核心。 對映檔案中有很多屬性,常用的就是parameterType(輸入型別)、resultType(輸出型別)、resultMap()、

java解析xml檔案的五種常見方法:DOM4JdompullSAXJdom

package com.zhidi.dom4jtest; import java.io.File; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import or

傳參在mybatis的sql對映檔案正確獲取

  1、單個引數: 非自定義物件 傳參:getStuById(Integer id); 取值:#{id} 單個基本型別引數,隨便取值都行;#{ok} 物件: 傳參:saveStudent(Student student) 取值:#{屬性名} 2、多個引數: 傳參:getStudentB

去掉IntelliJ IDEA生成的mybatis對映檔案黃色綠色的背景

IntelliJ IDEA 開啟 mybatis 的 xml 檔案時,對應的 xml 檔案中 sql 語句背景色總是有黃色或綠色的背景色。 提示(紅圈處)上已經說明,需要配置在 IDEA 中配置 data source (通常我們很少使用 IDE 去檢視資料庫內容,而是