1. #{}和${}的區別是什麼?
${}是Properties文件中的變量佔位符,它能夠用於標籤屬性值和sql內部,屬於靜態文本替換,好比${driver}會被靜態替換爲com.mysql.jdbc.Driver。
#{}是sql的參數佔位符,Mybatis會將sql中的#{}替換爲?號,在sql執行前會使用PreparedStatement的參數設置方法,按序給sql的?號佔位符設置參數值,好比ps.setInt(0, parameterValue)。
後者能夠防止SQL注入,前者不能夠。html
2. Xml映射文件中,除了常見的select|insert|updae|delete標籤以外,還有哪些?
還不少其餘的標籤,<resultMap>、<parameterMap>、<sql>、<include>、<selectKey>,加上動態sql的9個標籤,trim|where|set|foreach|if|choose|when|otherwise|bind等。java
3. 最佳實踐中,一般一個Xml映射文件,都會寫一個Dao接口與之對應,這個Dao接口的工做原理是什麼?Dao接口裏的方法,參數不一樣時,方法能重載嗎?
Dao接口,就是人們常說的Mapper接口,接口的全限名,就是映射文件中的namespace的值,接口的方法名,就是映射文件中MappedStatement的id值,接口方法內的參數,就是傳遞給sql的參數。Mapper接口是沒有實現類的,當調用接口方法時,接口全限名+方法名拼接字符串做爲key值,可惟必定位一個MappedStatement。在Mybatis中,每個<select>、<insert>、<update>、<delete>標籤,都會被解析爲一個MappedStatement對象。
Dao接口裏的方法,是不能重載的,由於是全限名+方法名的保存和尋找策略。
Dao接口的工做原理是JDK動態代理,Mybatis運行時會使用JDK動態代理爲Dao接口生成代理proxy對象,代理對象proxy會攔截接口方法,轉而執行MappedStatement所表明的sql,而後將sql執行結果返回。mysql
4. 簡述Mybatis的插件運行原理,以及如何編寫一個插件。
Mybatis僅能夠編寫針對ParameterHandler、ResultSetHandler、StatementHandler、Executor這4種接口的插件,Mybatis使用JDK的動態代理,爲須要攔截的接口生成代理對象以實現接口方法攔截功能,每當執行這4種接口對象的方法時,就會進入攔截方法,具體就是InvocationHandler的invoke()方法,固然,只會攔截那些你指定須要攔截的方法。
實現Mybatis的Interceptor接口並複寫intercept()方法,而後在給插件編寫註解,指定要攔截哪個接口的哪些方法便可,記住,別忘了在配置文件中配置你編寫的插件。sql
5. Mybatis是如何將sql執行結果封裝爲目標對象並返回的?都有哪些映射形式?
第一種是使用<resultMap>標籤,逐必定義列名和對象屬性名之間的映射關係。
第二種是使用sql列的別名功能,將列別名書寫爲對象屬性名。緩存
6. 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
7. Mybatis的Xml映射文件中,不一樣的Xml映射文件,id是否能夠重複?
不一樣的Xml映射文件,若是配置了namespace,那麼id能夠重複;若是沒有配置namespace,那麼id不能重複;畢竟namespace不是必須的,只是最佳實踐而已。
緣由就是namespace+id是做爲Map<String, MappedStatement>的key使用的,若是沒有namespace,就剩下id,那麼,id重複會致使數據互相覆蓋。有了namespace,天然id就能夠重複,namespace不一樣,namespace+id天然也就不一樣。app
8. 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生命週期範圍內。ide
9. Mybatis是否能夠映射Enum枚舉類?
Mybatis能夠映射枚舉類,不單能夠映射枚舉類,Mybatis能夠映射任何對象到表的一列上。映射方式爲自定義一個TypeHandler,實現TypeHandler的setParameter()和getResult()接口方法。
TypeHandler有兩個做用,一是完成從javaType至jdbcType的轉換,二是完成jdbcType至javaType的轉換,體現爲setParameter()和getResult()兩個方法,分別表明設置sql問號佔位符參數和獲取列查詢結果。spa
10. Mybatis映射文件中,若是A標籤經過include引用了B標籤的內容,請問,B標籤可否定義在A標籤的後面,仍是說必須定義在A標籤的前面?
雖然Mybatis解析Xml映射文件是按照順序解析的,可是,被引用的B標籤依然能夠定義在任何地方,Mybatis均可以正確識別。
原理是: Mybatis解析A標籤,發現A標籤引用了B標籤,可是B標籤還沒有解析到,尚不存在,此時,Mybatis會將A標籤標記爲未解析狀態,而後繼續解析餘下的標籤,包含B標籤,待全部標籤解析完畢,Mybatis會從新解析那些被標記爲未解析的標籤,此時再解析A標籤時,B標籤已經存在,A標籤也就能夠正常解析完成了。插件
11. mybatis 中的trim有什麼做用?
trim 的prefixOverrides 屬性會忽略經過管道分隔的文本序列。它帶來的結果就是全部在 prefixOverrides 屬性中指定的內容將被移除,而且插入 prefix 屬性中指定的內容。
以下示例:
<trim prefix="WHERE" prefixoverride="AND |OR">
<if test="id != null"> AND id=#{id}</if>
<if test="name!= null"> AND name=#{name}</if>
</trim>
id和name的值都不爲null時對應的SQL爲:select * from user where id = 'xx' and name = 'xx'
上面兩個屬性的意思以下:
prefix:前綴
prefixoverride:去掉第一個and或者是or
再看以下示例:
update user <trim prefix="set" suffixoverride="," suffix=" where id = #{id} "> <if test="name != null"> name=#{name} , </if> <if test="age != null"> age=#{age} , </if> </trim> name和age都不爲null時對應的SQL爲:update user set name='xx' , age='xx' where id='x' 上面三個屬性的意義以下: prefix:前綴 suffixoverride:去掉最後一個逗號(也能夠是其餘的標記,就像是上面前綴中的and同樣) suffix:後綴
12. MyBatis中命名空間(namespace)的做用? 在大型項目中,可能存在大量的SQL語句,這時候爲每一個SQL語句起一個惟一的標識(ID)就變得並不容易了。爲了解決這個問題,在MyBatis中,能夠爲每一個映射文件起一個惟一的命名空間,這樣定義在這個映射文件中的每一個SQL語句就成了定義在這個命名空間中的一個ID。只要咱們可以保證每一個命名空間中這個ID是惟一的,即便在不一樣映射文件中的語句ID相同,也不會再產生衝突了。