Mybatis 相關(guān)

一、Ibatis和Mybatis

  1. Ibatis:2010年运褪,apache 的 Ibatis 框架停止更新难述,并移交給了 google 團(tuán)隊(duì),同時(shí)更名為 MyBatis吐句。從2010年后 Ibatis 再?zèng)]更新過(guò)胁后,徹底變成了一個(gè)孤兒框架。一個(gè)沒(méi)人維護(hù)的框架注定被 MyBatis 拍在沙灘上嗦枢。
  2. Mybatis:Ibatis 的升級(jí)版本攀芯。

二、Mybatis DAO接口為什么不需要實(shí)現(xiàn)類(lèi)文虏?

Mybatis 實(shí)現(xiàn)了 DAO 接口 與 xml 映射文件的綁定侣诺,自動(dòng)生成接口的具體實(shí)現(xiàn),使用起來(lái)變得更加省事和方便氧秘。

1??Dao 接口年鸳,就是常說(shuō)的 Mapper 接口:
①接口的全限名,就是映射文件中的 namespace 的值丸相。
②接口的方法名搔确,就是映射文件中 MappedStatement 的 id 值。
③接口方法內(nèi)的參數(shù)灭忠,就是傳遞給 sql 的參數(shù)膳算。

2??Dao 接口是沒(méi)有實(shí)現(xiàn)類(lèi)的,當(dāng)調(diào)用接口方法時(shí)弛作,接口全限名+方法名拼接字符串作為 key 值涕蜂,可唯一定位一個(gè) MappedStatement。舉例:
com.wg.mappers.ZooDao.selById映琳,可以唯一找到 namespace 為com.wg.mappers.ZooDao 下面 id = selById 的 MappedStatement机隙。在 Mybatis 中蜘拉,每一個(gè) select、insert有鹿、update旭旭、delete 標(biāo)簽,都會(huì)被解析為一個(gè) MappedStatement 對(duì)象印颤。

3??Dao 接口里的方法您机,是不能重載的穿肄,因?yàn)槭侨廾?方法名的保存和尋找策略年局。Dao 接口的工作原理是 JDK 的動(dòng)態(tài)代理,Mybatis 運(yùn)行時(shí)會(huì)使用 JDK 動(dòng)態(tài)代理為 Dao 接口生成代理 proxy 對(duì)象(如使用 Spring 會(huì)注入到容器中)咸产,代理對(duì)象 proxy 會(huì)攔截接口方法矢否,轉(zhuǎn)而執(zhí)行 MappedStatement 所代表的 sql,然后將 sql 執(zhí)行結(jié)果返回脑溢。

三僵朗、什么情況用注解,什么情況用xml綁定屑彻?

  1. 注解使用情況:Sql語(yǔ)句簡(jiǎn)單時(shí)
  2. xml綁定使用情況:xml綁定 (@RequestMap用來(lái)綁定xml文件)

四验庙、Mybatis核心處理類(lèi)叫什么?

SqlSession

五、Mybatis是用來(lái)做什么的社牲?為什么不直接用jdbc?

MyBatis 是一個(gè)支持普通 SQL 查詢粪薛,存儲(chǔ)過(guò)程和高級(jí)映射的優(yōu)秀持久層框架。
相對(duì)于 JDBC搏恤,MyBatis 有以下優(yōu)點(diǎn):
①把 sql 語(yǔ)句從 Java 中獨(dú)立出來(lái)违寿,統(tǒng)一管理,便于維護(hù)和管理熟空。
②封裝了底層的 JDBC藤巢,API 的調(diào)用,并且能夠?qū)⒔Y(jié)果集自動(dòng)轉(zhuǎn)換成 JavaBean 對(duì)象息罗,簡(jiǎn)化了 Java 數(shù)據(jù)庫(kù)編程的重復(fù)工作掂咒。
③提供了緩存功能。
④入?yún)o(wú)需用對(duì)象封裝(或者map封裝)迈喉,使用 @Param 注解俏扩。

六、#{}和${}的區(qū)別

區(qū)別
理解

七弊添、怎么處理實(shí)體類(lèi)中的屬性名和表中的字段名不一致录淡?

名稱對(duì)應(yīng)

八、 模糊查詢like語(yǔ)句該怎么寫(xiě)?

模糊查詢like語(yǔ)句

九油坝、Mybatis 的緩存分幾種嫉戚?各有什么作用刨裆?

MyBatis 中的緩存分為兩種:一級(jí)緩存和二級(jí)緩存。一級(jí)緩存是 sqlSession 級(jí)別的彬檀,二級(jí)緩存是 mapper 級(jí)別的帆啃。當(dāng)使用同一個(gè) sqlSession 時(shí),查詢到的數(shù)據(jù)可能是一級(jí)緩存窍帝;而當(dāng)使用同一個(gè) mapper 是努潘,查詢到的數(shù)據(jù)可能是二級(jí)緩存。一級(jí)緩存默認(rèn)開(kāi)啟的坤学。二級(jí)緩存需要配置才開(kāi)啟疯坤,當(dāng)配置文件配置了cacheEnabled=true時(shí),就會(huì)開(kāi)啟二級(jí)緩存深浮。

十压怠、Mybatis是如何進(jìn)行分頁(yè)的?分頁(yè)插件的原理是什么飞苇?

  1. Mybatis 使用 RowBounds 對(duì)象進(jìn)行分頁(yè)菌瘫,它是針對(duì) ResultSet 結(jié)果集執(zhí)行的內(nèi)存分頁(yè),而非物理分頁(yè)布卡。
  2. 也可以在 sql 內(nèi)直接書(shū)寫(xiě)帶有物理分頁(yè)的參數(shù)來(lái)完成物理分頁(yè)功能雨让,也可以使用分頁(yè)插件來(lái)完成物理分頁(yè)。分頁(yè)插件的基本原理是使用 Mybatis 提供的插件接口忿等,實(shí)現(xiàn)自定義插件栖忠,在插件的攔截方法內(nèi)攔截待執(zhí)行的 sql,然后重寫(xiě) sql这弧,根據(jù) dialect 方言娃闲,添加對(duì)應(yīng)的物理分頁(yè)語(yǔ)句和物理分頁(yè)參數(shù)。

十一匾浪、Mybatis是如何將sql執(zhí)行結(jié)果封裝為目標(biāo)對(duì)象并返回的皇帮?都有哪些映射形式?

1.使用resultMap標(biāo)簽蛋辈,逐一定義列名和對(duì)象屬性名之間的映射關(guān)系属拾。
2.使用sql列的別名功能,將列別名書(shū)寫(xiě)為對(duì)象屬性名冷溶,比如AcctName AS NAME渐白,對(duì)象屬性名一般是小寫(xiě),但是列名不區(qū)分大小寫(xiě)逞频,Mybatis會(huì)忽略列名大小寫(xiě)纯衍,智能找到與之對(duì)應(yīng)對(duì)象屬性名,你甚至可以寫(xiě)成AcctName AS NaMe苗胀,Mybatis一樣可以正常工作襟诸。
有了列名與屬性名的映射關(guān)系后瓦堵,Mybatis通過(guò)反射創(chuàng)建對(duì)象,同時(shí)使用反射給對(duì)象的屬性逐一賦值并返回歌亲,那些找不到映射關(guān)系的屬性菇用,是無(wú)法完成賦值的。

十二陷揪、如何執(zhí)行批量插入

首先惋鸥,創(chuàng)建一個(gè)簡(jiǎn)單的insert語(yǔ)句:

<insert id=”insertName”> 
 insert into acctInfo (name) values (#{value}) 
</insert>

然后在java代碼中像下面這樣執(zhí)行批處理插入:

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(); 
  }

十三、如何獲取自動(dòng)生成的(主)鍵值?

insert 方法總是返回一個(gè)int值 ~~ 這個(gè)值代表的是插入的行數(shù)悍缠。
而自動(dòng)生成的鍵值在 insert 方法執(zhí)行完后可以被設(shè)置到傳入的參數(shù)對(duì)象中卦绣。
示例:

 <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已經(jīng)被設(shè)置到對(duì)象中 
 system.out.println("rows inserted = " + rows); 
 system.out.println("generated key value = " + name.getId());

十四、在mapper中如何傳遞多個(gè)參數(shù)?

第1種:

//DAO層的函數(shù)
public User selUser(String name,String area); 
//對(duì)應(yīng)的xml,#{0}代表接收的是dao層中的第一個(gè)參數(shù)扮休,#{1}代表dao層中第二參數(shù)迎卤,
更多參數(shù)一致往后加即可拴鸵。
<select id="selectUser" resultMap="BaseResultMap"> 
 select * from userInfo where user_name = #{0} and user_area=#{1} 
</select> 

第2種: 使用 @param 注解:

 public interface usermapper { 
 user selUser(@param("userName") String userName, 
 @param("hashedPassword") String hashedPassword); 
 }
然后,就可以在xml像下面這樣使用(推薦封裝為一個(gè)map,作為單個(gè)參數(shù)傳遞給mapper): 
 <select id="selUser" resultType="user"> 
 select id, username, hashedPassword 
 from userInfo 
 where userName = #{username} 
 and hashedPassword = #{hashedPassword} 
 </select>

十五玷坠、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的功能瞎饲。

十六口叙、Mybatis的Xml映射文件中,不同的Xml映射文件嗅战,id是否可以重復(fù)妄田?

不同的Xml映射文件,如果配置了namespace驮捍,那么id可以重復(fù)疟呐;如果沒(méi)有配置namespace,那么id不能重復(fù)东且;畢竟namespace不是必須的启具,只是最佳實(shí)踐而已。
原因就是namespace+id是作為Map<String, MappedStatement>的key使用的珊泳,如果沒(méi)有namespace鲁冯,就剩下id囤踩。那么,id重復(fù)會(huì)導(dǎo)致數(shù)據(jù)互相覆蓋晓褪。有了namespace堵漱,自然id就可以重復(fù),namespace不同涣仿,namespace+id自然也就不同勤庐。

十七、為什么說(shuō)Mybatis是半自動(dòng)ORM映射工具好港?它與全自動(dòng)的區(qū)別在哪里愉镰?

Hibernate屬于全自動(dòng)ORM映射工具,使用Hibernate查詢關(guān)聯(lián)對(duì)象或者關(guān)聯(lián)集合對(duì)象時(shí)钧汹,可以根據(jù)對(duì)象關(guān)系模型直接獲取丈探,所以它是全自動(dòng)的。而Mybatis在查詢關(guān)聯(lián)對(duì)象或關(guān)聯(lián)集合對(duì)象時(shí)拔莱,需要手動(dòng)編寫(xiě)sql來(lái)完成碗降,所以,稱之為半自動(dòng)ORM映射工具塘秦。

十八讼渊、sql預(yù)編譯

sql 預(yù)編譯指的是數(shù)據(jù)庫(kù)驅(qū)動(dòng)在發(fā)送 sql 語(yǔ)句和參數(shù)給 DBMS 數(shù)據(jù)庫(kù)管理系統(tǒng)(Database Management System)之前對(duì) sql 語(yǔ)句進(jìn)行編譯材蹬,這樣 DBMS 執(zhí)行 sql 時(shí)引润,就不需要重新編譯。
為什么需要預(yù)編譯嘿棘?
JDBC 中使用對(duì)象 PreparedStatement 來(lái)抽象預(yù)編譯語(yǔ)句须误,使用預(yù)編譯挨稿。

  1. 預(yù)編譯階段可以優(yōu)化 sql 的執(zhí)行。
    預(yù)編譯之后的 sql 多數(shù)情況下可以直接執(zhí)行京痢,DBMS不需要再次編譯奶甘,越復(fù)雜的sql,編譯的復(fù)雜度將越大历造,預(yù)編譯階段可以合并多次操作為一個(gè)操作甩十。
  2. 預(yù)編譯語(yǔ)句對(duì)象可以重復(fù)利用。
    SQL語(yǔ)句會(huì)預(yù)編譯在數(shù)據(jù)庫(kù)系統(tǒng)中吭产。執(zhí)行計(jì)劃同樣會(huì)被緩存起來(lái)侣监,它允許數(shù)據(jù)庫(kù)做參數(shù)化查詢。使用預(yù)處理語(yǔ)句比普通的查詢更快臣淤,因?yàn)樗龅墓ぷ鞲匍厦埂0岩粋€(gè) sql 預(yù)編譯后產(chǎn)生的 PreparedStatement 對(duì)象緩存下來(lái),下次對(duì)于同一個(gè)sql邑蒋,可以直接使用這個(gè)緩存的PreparedState 對(duì)象姓蜂。它擁有更佳的性能優(yōu)勢(shì)按厘,因?yàn)閿?shù)據(jù)庫(kù)對(duì)SQL語(yǔ)句的分析,編譯钱慢,優(yōu)化已經(jīng)在第一次查詢前完成了逮京。
  3. PreparedStatement可以防止SQL注入式攻擊
    SQL 注入攻擊:SQL 注入是利用某些系統(tǒng)沒(méi)有對(duì)用戶輸入的數(shù)據(jù)進(jìn)行充分的檢查,而在用戶輸入數(shù)據(jù)中注入非法的 SQL 語(yǔ)句段或命令束莫,從而利用系統(tǒng)的 SQL 引擎完成惡意行為的做法懒棉。

MyBatis 默認(rèn)情況下,將對(duì)所有的 sql 進(jìn)行預(yù)編譯览绿。

MySQL預(yù)編譯源碼解析:
MySQL的預(yù)編譯源碼在 com.mysql.jdbc.ConnectionImpl 類(lèi)中策严,如下:


說(shuō)明:
MyBatis在調(diào)用 connection 進(jìn)行 sql 預(yù)編譯之前,會(huì)對(duì)sql語(yǔ)句進(jìn)行動(dòng)態(tài)解析饿敲,動(dòng)態(tài)解析主要包含如下的功能:

  • 占位符的處理
  • 動(dòng)態(tài)sql的處理
  • 參數(shù)類(lèi)型校驗(yàn)
    MyBatis強(qiáng)大的動(dòng)態(tài)SQL功能的具體實(shí)現(xiàn)就在此妻导。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市怀各,隨后出現(xiàn)的幾起案子倔韭,更是在濱河造成了極大的恐慌,老刑警劉巖渠啤,帶你破解...
    沈念sama閱讀 221,635評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件狐肢,死亡現(xiàn)場(chǎng)離奇詭異添吗,居然都是意外死亡沥曹,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)碟联,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)妓美,“玉大人,你說(shuō)我怎么就攤上這事鲤孵『埃” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,083評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵普监,是天一觀的道長(zhǎng)贵试。 經(jīng)常有香客問(wèn)我,道長(zhǎng)凯正,這世上最難降的妖魔是什么毙玻? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,640評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮廊散,結(jié)果婚禮上桑滩,老公的妹妹穿的比我還像新娘。我一直安慰自己允睹,他們只是感情好运准,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布幌氮。 她就那樣靜靜地躺著,像睡著了一般胁澳。 火紅的嫁衣襯著肌膚如雪该互。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,262評(píng)論 1 308
  • 那天韭畸,我揣著相機(jī)與錄音慢洋,去河邊找鬼。 笑死陆盘,一個(gè)胖子當(dāng)著我的面吹牛普筹,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播隘马,決...
    沈念sama閱讀 40,833評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼太防,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了酸员?” 一聲冷哼從身側(cè)響起蜒车,我...
    開(kāi)封第一講書(shū)人閱讀 39,736評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎幔嗦,沒(méi)想到半個(gè)月后酿愧,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,280評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡邀泉,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評(píng)論 3 340
  • 正文 我和宋清朗相戀三年嬉挡,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片汇恤。...
    茶點(diǎn)故事閱讀 40,503評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡庞钢,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出因谎,到底是詐尸還是另有隱情基括,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布财岔,位于F島的核電站风皿,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏匠璧。R本人自食惡果不足惜桐款,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望患朱。 院中可真熱鬧鲁僚,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,340評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至拓挥,卻和暖如春唠梨,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背侥啤。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,460評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工当叭, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人盖灸。 一個(gè)月前我還...
    沈念sama閱讀 48,909評(píng)論 3 376
  • 正文 我出身青樓蚁鳖,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親赁炎。 傳聞我的和親對(duì)象是個(gè)殘疾皇子醉箕,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容