1.#{}和${}的區(qū)別是什么?
#{}是預(yù)編譯處理,${}是字符串替換,
Mybatis在處理#{}時(shí),在SQL執(zhí)行之前,將SQL發(fā)送給數(shù)據(jù)庫(kù)進(jìn)行編譯,會(huì)將sql中的#{}替換為?號(hào),在執(zhí)行時(shí)調(diào)用PreparedStatement的set方法來(lái)賦值;
Mybatis在處理 ${} 時(shí),就是把${}替換成變量的值,直接進(jìn)行sql拼接。
使用#{}可以有效的防止SQL注入,提高系統(tǒng)安全性。
2.當(dāng)實(shí)體類(lèi)中的屬性名和表中的字段名不一樣 ,怎么辦 ?
(1)修改數(shù)據(jù)庫(kù)中的字段名
(2)通過(guò)<resultMap>來(lái)映射字段名和實(shí)體類(lèi)屬性名的一一對(duì)應(yīng)關(guān)系
3.模糊查詢(xún)like語(yǔ)句該怎么寫(xiě)?
(1)在Java代碼中添加sql通配符。
(2)在sql語(yǔ)句中拼接通配符,會(huì)引起sql注入
4.通常一個(gè)Xml映射文件,都會(huì)寫(xiě)一個(gè)Dao接口與之對(duì)應(yīng),請(qǐng)問(wèn),這個(gè)Dao接口的工作原理是什么?Dao接口里的方法,參數(shù)不同時(shí),方法能重載嗎?
- Dao接口,就是人們常說(shuō)的Mapper接口,接口的全限名,就是映射文件中的namespace的值,接口的方法名,就是映射文件中MappedStatement的id值,接口方法內(nèi)的參數(shù),就是傳遞給sql的參數(shù)。Mapper接口是沒(méi)有實(shí)現(xiàn)類(lèi)的,當(dāng)調(diào)用接口方法時(shí),接口全限名+方法名拼接字符串作為key值,可唯一定位一個(gè)MappedStatement。
- Dao接口里的方法,是不能重載的,因?yàn)槭侨廾?方法名的保存和尋找策略。
- Dao接口的工作原理是JDK動(dòng)態(tài)代理,Mybatis運(yùn)行時(shí)會(huì)使用JDK動(dòng)態(tài)代理為Dao接口生成代理proxy對(duì)象,代理對(duì)象proxy會(huì)攔截接口方法,轉(zhuǎn)而執(zhí)行MappedStatement所代表的sql,然后將sql執(zhí)行結(jié)果返回。
5.Mybatis是如何將sql執(zhí)行結(jié)果封裝為目標(biāo)對(duì)象并返回的?都有哪些映射形式?
- 第一種是使用<resultMap>標(biāo)簽,逐一定義列名和對(duì)象屬性名之間的映射關(guān)系。
- 第二種是使用sql列的別名功能,將列別名書(shū)寫(xiě)為對(duì)象屬性名,比如 T_NAME AS NAME,對(duì)象屬性名一般是name,小寫(xiě),但是列名不區(qū)分大小寫(xiě),Mybatis會(huì)忽略列名大小寫(xiě),智能找到與之對(duì)應(yīng)對(duì)象屬性名,你甚至可以寫(xiě)成T_NAME AS NaMe,Mybatis一樣可以正常工作。有了列名與屬性名的映射關(guān)系后,Mybatis通過(guò)反射創(chuàng)建對(duì)象,同時(shí)使用反射給對(duì)象的屬性逐一賦值并返回,那些找不到映射關(guān)系的屬性,是無(wú)法完成賦值的。
6.如何獲取自動(dòng)生成的(主)鍵值?
insert 方法總是返回一個(gè)int值 - 這個(gè)值代表的是插入的行數(shù)。
通過(guò)屬性u(píng)segeneratedkeys=””和keyproperty=””來(lái)獲取生成的鍵值,自動(dòng)生成的鍵值被傳入的參數(shù)對(duì)象中。
7.Mybatis動(dòng)態(tài)sql是做什么的?都有哪些動(dòng)態(tài)sql?能簡(jiǎn)述一下動(dòng)態(tài)sql的執(zhí)行原理不?
Mybatis動(dòng)態(tài)sql可以讓我們?cè)赬ml映射文件內(nèi),以標(biāo)簽的形式編寫(xiě)動(dòng)態(tài)sql,完成邏輯判斷和動(dòng)態(tài)拼接sql的功能。
Mybatis提供了9種動(dòng)態(tài)sql標(biāo)簽:trim|where|set|foreach|if|choose|when|otherwise|bind。
其執(zhí)行原理為,使用OGNL從sql參數(shù)對(duì)象中計(jì)算表達(dá)式的值,根據(jù)表達(dá)式的值動(dòng)態(tài)拼接sql,以此來(lái)完成動(dòng)態(tài)sql的功能。
8.Mybatis的Xml映射文件中,不同的Xml映射文件,id是否可以重復(fù)?
不同的Xml映射文件,如果配置了namespace,那么id可以重復(fù);如果沒(méi)有配置namespace,那么id不能重復(fù);畢竟namespace不是必須的,只是最佳實(shí)踐而已。
9.為什么說(shuō)Mybatis是半自動(dòng)ORM映射工具?它與全自動(dòng)的區(qū)別在哪里?
Hibernate屬于全自動(dòng)ORM映射工具,使用Hibernate查詢(xún)關(guān)聯(lián)對(duì)象或者關(guān)聯(lián)集合對(duì)象時(shí),可以根據(jù)對(duì)象關(guān)系模型直接獲取,所以它是全自動(dòng)的。而Mybatis在查詢(xún)關(guān)聯(lián)對(duì)象或關(guān)聯(lián)集合對(duì)象時(shí),需要手動(dòng)編寫(xiě)sql來(lái)完成,所以,稱(chēng)之為半自動(dòng)ORM映射工具。
10.Mybatis的一級(jí)、二級(jí)緩存:
1)一級(jí)緩存: 基于 PerpetualCache 的 HashMap 本地緩存,其存儲(chǔ)作用域?yàn)?Session,當(dāng) Session flush 或 close 之后,該 Session 中的所有 Cache 就將清空,默認(rèn)打開(kāi)一級(jí)緩存。
2)二級(jí)緩存與一級(jí)緩存其機(jī)制相同,默認(rèn)也是采用 PerpetualCache,HashMap 存儲(chǔ),不同在于其存儲(chǔ)作用域?yàn)?Mapper(Namespace),并且可自定義存儲(chǔ)源,如 Ehcache。默認(rèn)不打開(kāi)二級(jí)緩存,要開(kāi)啟二級(jí)緩存,使用二級(jí)緩存屬性類(lèi)需要實(shí)現(xiàn)Serializable序列化接口(可用來(lái)保存對(duì)象的狀態(tài)),可在它的映射文件中配置<cache/> ;
3)對(duì)于緩存數(shù)據(jù)更新機(jī)制,當(dāng)某一個(gè)作用域(一級(jí)緩存 Session/二級(jí)緩存Namespaces)的進(jìn)行了C/U/D 操作后,默認(rèn)該作用域下所有 select 中的緩存將被 clear。
11.什么是MyBatis的接口綁定,有什么好處?
接口映射就是在MyBatis中任意定義接口,然后把接口里面的方法和SQL語(yǔ)句綁定, 我們直接調(diào)用接口方法就可以,這樣比起原來(lái)了SqlSession提供的方法我們可以有更加靈活的選擇和設(shè)置.
12.接口綁定有幾種實(shí)現(xiàn)方式,分別是怎么實(shí)現(xiàn)的?
接口綁定有兩種實(shí)現(xiàn)方式,一種是通過(guò)注解綁定,就是在接口的方法上面加上 @Select、@Update等注解,里面包含Sql語(yǔ)句來(lái)綁定;另外一種就是通過(guò)xml里面寫(xiě)SQL來(lái)綁定, 在這種情況下,要指定xml映射文件里面的namespace必須為接口的全路徑名.
13.什么情況下用注解綁定,什么情況下用xml綁定 ?
當(dāng)Sql語(yǔ)句比較簡(jiǎn)單時(shí)候,用注解綁定, 當(dāng)SQL語(yǔ)句比較復(fù)雜時(shí)候,用xml綁定,一般用xml綁定的比較多。
14.Mybatis分層結(jié)構(gòu)
15.Mybatis都有哪些Executor執(zhí)行器?它們之間的區(qū)別是什么?
Mybatis有三種基本的Executor執(zhí)行器,SimpleExecutor、ReuseExecutor、BatchExecutor。
SimpleExecutor:每執(zhí)行一次update或select,就開(kāi)啟一個(gè)Statement對(duì)象,用完立刻關(guān)閉Statement對(duì)象。
ReuseExecutor:執(zhí)行update或select,以sql作為key查找Statement對(duì)象,存在就使用,不存在就創(chuàng)建,用完后,不關(guān)閉Statement對(duì)象,而是放置于Map<String, Statement>內(nèi),供下一次使用。簡(jiǎn)言之,就是重復(fù)使用Statement對(duì)象。
BatchExecutor:執(zhí)行update(沒(méi)有select,JDBC批處理不支持select),將所有sql都添加到批處理中(addBatch()),等待統(tǒng)一執(zhí)行(executeBatch()),它緩存了多個(gè)Statement對(duì)象,每個(gè)Statement對(duì)象都是addBatch()完畢后,等待逐一執(zhí)行executeBatch()批處理。與JDBC批處理相同。
作用范圍:Executor的這些特點(diǎn),都嚴(yán)格限制在SqlSession生命周期范圍內(nèi)
16.Mybatis中如何指定使用哪一種Executor執(zhí)行器?
在Mybatis配置文件中,可以指定默認(rèn)的ExecutorType執(zhí)行器類(lèi)型,也可以手動(dòng)給DefaultSqlSessionFactory的創(chuàng)建SqlSession的方法傳遞ExecutorType類(lèi)型參數(shù)。
17.Mybatis映射文件中,如果A標(biāo)簽通過(guò)include引用了B標(biāo)簽的內(nèi)容,請(qǐng)問(wèn),B標(biāo)簽?zāi)芊穸x在A(yíng)標(biāo)簽的后面,還是說(shuō)必須定義在A(yíng)標(biāo)簽的前面?
雖然Mybatis解析Xml映射文件是按照順序解析的,但是,被引用的B標(biāo)簽依然可以定義在任何地方,Mybatis都可以正確識(shí)別。
原理是,Mybatis解析A標(biāo)簽,發(fā)現(xiàn)A標(biāo)簽引用了B標(biāo)簽,但是B標(biāo)簽尚未解析到,尚不存在,此時(shí),Mybatis會(huì)將A標(biāo)簽標(biāo)記為未解析狀態(tài),然后繼續(xù)解析余下的標(biāo)簽,包含B標(biāo)簽,待所有標(biāo)簽解析完畢,Mybatis會(huì)重新解析那些被標(biāo)記為未解析的標(biāo)簽,此時(shí)再解析A標(biāo)簽時(shí),B標(biāo)簽已經(jīng)存在,A標(biāo)簽也就可以正常解析完成了。
18.使用MyBatis的mapper接口調(diào)用有哪些要求?
(1)Mapper接口方法名和mapper.xml中定義的每個(gè)sql的id相同
(2)Mapper接口中輸入的參數(shù)類(lèi)型和mapper.xml中定義的每個(gè)sql的ParameterType相同
(3)Mapper接口中輸出的參數(shù)類(lèi)型和mapper.xml中定義的每個(gè)sql的resultType相同
(4)Mapper.xml文件中的namespace即是接口的類(lèi)路徑
19.Statement和PrepareStatement的區(qū)別
PreparedStatement:表示預(yù)編譯的 SQL 語(yǔ)句的對(duì)象。
(1)PrepareStatement可以使用占位符,是預(yù)編譯的,批處理比Statement效率高
(2)在對(duì)數(shù)據(jù)庫(kù)只執(zhí)行一次性存取的時(shí)侯,用 Statement 對(duì)象進(jìn)行處理。
(3)PreparedStatement的第一次執(zhí)行消耗是很高的. 它的性能體現(xiàn)在后面的重復(fù)執(zhí)行