Mybatis面試題

1蒸辆、什么是Mybatis?

(1)Mybatis是一個(gè)半ORM(對(duì)象關(guān)系映射)框架析既,它內(nèi)部封裝了JDBC躬贡,開發(fā)時(shí)只需要關(guān)注SQL語句本身,不需要花費(fèi)精力去處理加載驅(qū)動(dòng)眼坏、創(chuàng)建連接拂玻、創(chuàng)建statement等繁雜的過程。程序員直接編寫原生態(tài)sql空骚,可以嚴(yán)格控制sql執(zhí)行性能,靈活度高擂仍。

(2)MyBatis 可以使用 XML 或注解來配置和映射原生信息囤屹,將 POJO映射成數(shù)據(jù)庫中的記錄,避免了幾乎所有的 JDBC 代碼和手動(dòng)設(shè)置參數(shù)以及獲取結(jié)果集逢渔。

(3)通過xml 文件或注解的方式將要執(zhí)行的各種 statement 配置起來肋坚,并通過java對(duì)象和 statement中sql的動(dòng)態(tài)參數(shù)進(jìn)行映射生成最終執(zhí)行的sql語句,最后由mybatis框架執(zhí)行sql并將結(jié)果映射為java對(duì)象并返回肃廓。(從執(zhí)行sql到返回result的過程)智厌。

2、Mybaits的優(yōu)點(diǎn):

(1)基于SQL語句編程盲赊,相當(dāng)靈活汰具,不會(huì)對(duì)應(yīng)用程序或者數(shù)據(jù)庫的現(xiàn)有設(shè)計(jì)造成任何影響搞动,SQL寫在XML里,解除sql與程序代碼的耦合,便于統(tǒng)一管理巷挥;提供XML標(biāo)簽,支持編寫動(dòng)態(tài)SQL語句纪岁,并可重用毁欣。

(2)與JDBC相比,減少了50%以上的代碼量缀台,消除了JDBC大量冗余的代碼棠赛,不需要手動(dòng)開關(guān)連接;

(3)很好的與各種數(shù)據(jù)庫兼容(因?yàn)镸yBatis使用JDBC來連接數(shù)據(jù)庫膛腐,所以只要JDBC支持的數(shù)據(jù)庫MyBatis都支持)睛约。

(4)能夠與Spring很好的集成;

(5)提供映射標(biāo)簽哲身,支持對(duì)象與數(shù)據(jù)庫的ORM字段關(guān)系映射痰腮;提供對(duì)象關(guān)系映射標(biāo)簽,支持對(duì)象關(guān)系組件維護(hù)律罢。

3膀值、MyBatis框架的缺點(diǎn):

(1)SQL語句的編寫工作量較大棍丐,尤其當(dāng)字段多、關(guān)聯(lián)表多時(shí)沧踏,對(duì)開發(fā)人員編寫SQL語句的功底有一定要求歌逢。

(2)SQL語句依賴于數(shù)據(jù)庫,導(dǎo)致數(shù)據(jù)庫移植性差翘狱,不能隨意更換數(shù)據(jù)庫秘案。

4、MyBatis框架適用場(chǎng)合:

(1)MyBatis專注于SQL本身潦匈,是一個(gè)足夠靈活的DAO層解決方案阱高。

(2)對(duì)性能的要求很高,或者需求變化較多的項(xiàng)目茬缩,如互聯(lián)網(wǎng)項(xiàng)目赤惊,MyBatis將是不錯(cuò)的選擇。

5凰锡、MyBatis與Hibernate有哪些不同未舟?

(1)Mybatis和hibernate不同,它不完全是一個(gè)ORM框架掂为,因?yàn)镸yBatis需要程序員自己編寫Sql語句裕膀。

(2)Mybatis直接編寫原生態(tài)sql,可以嚴(yán)格控制sql執(zhí)行性能勇哗,靈活度高昼扛,非常適合對(duì)關(guān)系數(shù)據(jù)模型要求不高的軟件開發(fā),因?yàn)檫@類軟件需求變化頻繁欲诺,一但需求變化要求迅速輸出成果野揪。但是靈活的前提是mybatis無法做到數(shù)據(jù)庫無關(guān)性,如果需要實(shí)現(xiàn)支持多種數(shù)據(jù)庫的軟件瞧栗,則需要自定義多套sql映射文件斯稳,工作量大。

(3)Hibernate對(duì)象/關(guān)系映射能力強(qiáng)迹恐,數(shù)據(jù)庫無關(guān)性好挣惰,對(duì)于關(guān)系模型要求高的軟件,如果用hibernate開發(fā)可以節(jié)省很多代碼殴边,提高效率憎茂。

6、#{}和${}的區(qū)別是什么锤岸?

#{}是預(yù)編譯處理竖幔,${}是字符串替換。

Mybatis在處理#{}時(shí)是偷,會(huì)將sql中的#{}替換為?號(hào)拳氢,調(diào)用PreparedStatement的set方法來賦值募逞;

Mybatis在處理{}時(shí),就是把{}替換成變量的值馋评。

使用#{}可以有效的防止SQL注入放接,提高系統(tǒng)安全性。

7留特、請(qǐng)寫出Mybatis核心配置文件MyBatis-config.xml的內(nèi)容纠脾?

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>


    <!--加載我們需要的properties文件  獲取連接四要素-->
    <properties resource="jdbc.properties"/>


    <settings>
        <!-- 全局性地啟用或禁用延遲加載。當(dāng)禁用時(shí)蜕青,所有關(guān)聯(lián)的配置都會(huì)立即加載苟蹈。 -->
        <setting name="lazyLoadingEnabled" value="true"/>
        <!--當(dāng)啟用后,一個(gè)有延遲加載屬性的對(duì)象的任何一個(gè)延遲屬性被加載時(shí)右核,該對(duì)象
的所有的屬性都會(huì)被加載慧脱。否則,所有屬性都是按需加載蒙兰。  -->
        <setting name="aggressiveLazyLoading" value="false"/>
        <!--全局關(guān)閉2級(jí)緩存  -->
        <!--<setting name="cacheEnabled" value="false"/>-->

    </settings>


    <!--創(chuàng)建類的別名-->
    <typeAliases>
        <!--只要是在mapper.xml文件中使用了cn.pb.bean包下面的任意類的時(shí)候磷瘤,無需再用全類名
        使用簡寫的類名
          之前應(yīng)該 cn.pb.bean.Student
          現(xiàn)在  Student
        -->
        <package name="cn.pb.bean"/>
    </typeAliases>


    <!--設(shè)置mybatis運(yùn)行環(huán)境  default默認(rèn)的運(yùn)行環(huán)境====environment id的屬性值-->
    <environments default="mysql">
       <environment id="mysql">
           <!--配置事務(wù)管理器-->
           <transactionManager type="JDBC"></transactionManager>
           <!--配置數(shù)據(jù)源 POOLED:mybatis自帶的數(shù)據(jù)源-->
           <dataSource type="POOLED">
               <property name="driver" value="${jdbc.driver}"/>
               <property name="url" value="${jdbc.url}"/>
               <property name="username" value="${jdbc.username}"/>
               <property name="password" value="${jdbc.password}"/>
           </dataSource>
       </environment>
    </environments>

    <!--配置需要的mapper文件-->
    <mappers>
        <mapper resource="mapper/StudentMapper.xml"/>
    </mappers>
</configuration>

8芒篷、什么是數(shù)據(jù)持久化以及ORM搜变?

  • 01.數(shù)據(jù)持久化的概念
    數(shù)據(jù)持久化就是將內(nèi)在中的數(shù)據(jù)模型轉(zhuǎn)換為存儲(chǔ)模型,以及將存儲(chǔ)模型轉(zhuǎn)換為內(nèi)在中的數(shù)據(jù)模型的統(tǒng)稱,數(shù)據(jù)模型可以是任何數(shù)據(jù)結(jié)構(gòu)或?qū)ο竽P?例如JavaBean對(duì)象;存儲(chǔ)模型可以是關(guān)系型數(shù)據(jù)庫表,XML文件,二進(jìn)制文件等.

  • 02.什么是ORM
    ORM(Object/Relational Mapping)中文翻譯為對(duì)象/關(guān)系型數(shù)據(jù)映射,它也可以理解為一種數(shù)據(jù)持久化技術(shù),其主要是把對(duì)象模型,例如JavaBean對(duì)象和關(guān)系型數(shù)據(jù)庫的表建立對(duì)應(yīng)關(guān)系,并且提供了一個(gè)通過JavaBean對(duì)象去操作數(shù)據(jù)庫表的機(jī)制.

  • 03.使用ORM技術(shù)的好處
    在實(shí)際開發(fā)中,程序員使用面向?qū)ο蟮募夹g(shù)操作數(shù)據(jù),而當(dāng)要把數(shù)據(jù)存儲(chǔ)起來時(shí),使用的卻是關(guān)系型數(shù)據(jù)庫,這樣就造成了很多的不便,ORM在對(duì)象模型和關(guān)系數(shù)據(jù)庫的表之間建立了一座橋梁,有了它,程序員就不需要再使用SQL語句操作數(shù)據(jù)庫中的表,直接操作JavaBean對(duì)象就可以實(shí)現(xiàn)數(shù)據(jù)的存儲(chǔ),查詢,更改和刪除等操作,Hibernate就是這樣一種技術(shù).

9、請(qǐng)寫出MybatisUtil工具類

package cn.pb.util;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

public class SessionFactoryUtil {
    //01.創(chuàng)建需要單例的對(duì)象實(shí)例
    private static SqlSessionFactory sessionFactory;


    //02.私有化構(gòu)造
    private SessionFactoryUtil(){}

    /**
     *  03.對(duì)外提供訪問的接口
     *     001.SqlSession的創(chuàng)建依賴SqlSessionFactory
     *     002.SqlSessionFactory依賴于SqlSessionFactoryBuilder
     *     003.SqlSessionFactoryBuilder依賴于配置文件
     *     004.獲取配置文件
     */
    public   static  synchronized SqlSession getSession(){
        //給我一個(gè)文件 返回一個(gè)輸入流 到 內(nèi)存中
        try {
            InputStream stream = Resources.getResourceAsStream("mybatis.xml");
            //判斷SqlSessionFactory是否為空
            if (sessionFactory==null){
                sessionFactory=new SqlSessionFactoryBuilder().build(stream);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        /**
         * 之前還需要寫一個(gè)finally用來關(guān)閉流针炉!  現(xiàn)在不需要   為什么不需要??
         * 01.查詢?cè)创abuild(stream)
         * 02.SqlSessionFactoryBuilder類中已經(jīng)關(guān)閉reader.close()
         * 03.所以我們?nèi)绻P(guān)閉流  會(huì)報(bào)錯(cuò)挠他!
         */
        return  sessionFactory.openSession();  //創(chuàng)建session返回
    }
}

10、請(qǐng)使用association節(jié)點(diǎn)實(shí)現(xiàn)根據(jù)用戶id查詢用戶信息以及對(duì)應(yīng)角色信息(Role實(shí)體類中有一個(gè)對(duì)象User,只寫SQL映射文件)篡帕?

 <!-- 01. 根據(jù)角色id 查詢出角色信息-->
<select id="selectRoleById"  resultMap="roleMap">
select id,name,userid from role where id=#{xxx}
</select>

        <!-- 02. 根據(jù)角色表中查詢結(jié)果中的userid 查詢用戶信息
       xxx就是resultmap中傳遞來的 userid-->
<select id="selectUserByUserId" resultType="User">
select userid,name from user where userid=#{xxx}
</select>

        <!--對(duì)應(yīng)的roleMap  這種方式 推薦使用  因?yàn)槭褂醚舆t加載-->
<resultMap id="rolrMap" type="Role">
<id property="id" column="id"/>
<result property="name" column="name"/>
<!-- Role有一個(gè)屬性的類型是 user   域?qū)傩?javaType:域?qū)傩詫?duì)應(yīng)的類型 -->
<association property="user" javaType="User" select="selectUserByUserId"
             column="userid"/>
</resultMap>

11殖侵、請(qǐng)使用collection節(jié)點(diǎn)實(shí)現(xiàn)獲取指定用戶的相關(guān)信息和地址列表(User實(shí)體類中有一個(gè)復(fù)雜類型的Address集合,只寫SQL映射文件)镰烧?

<!-- 01. 根據(jù)用戶id 查詢出用戶信息-->
<select id="selectUserById"  resultMap="userMap">
select id,name from user where id=#{xxx}
</select>

        <!-- 02. 根據(jù)用戶表中查詢結(jié)果中的userid 查詢地址信息
       xxx就是resultmap中傳遞來的 userid-->
<select id="selectAddressByUserId" resultType="Address">
select id,name,userid from address where userid=#{xxx}
</select>

        <!--對(duì)應(yīng)的userMap  這種方式 推薦使用  因?yàn)槭褂醚舆t加載-->
<resultMap id="userMap" type="User">
<id property="id" column="id"/>
<result property="name" column="name"/>
<!-- User有一個(gè)屬性的類型是 list   
javaType:域?qū)傩詫?duì)應(yīng)的類型 -->
<collection property="addresses" javaType="Address" select="selectAddressByUserId"
             column="userid"/>
</resultMap>

12拢军、MyBatis實(shí)現(xiàn)一對(duì)一有幾種方式?具體怎么操作的?

有聯(lián)合查詢和嵌套查詢,聯(lián)合查詢是幾個(gè)表聯(lián)合查詢,只查詢一次, 通過在resultMap里面配置association節(jié)點(diǎn)配置一對(duì)一的類就可以完成怔鳖;

嵌套查詢是先查一個(gè)表茉唉,根據(jù)這個(gè)表里面的結(jié)果的 外鍵id,去再另外一個(gè)表里面查詢數(shù)據(jù),也是通過association配置结执,但另外一個(gè)表的查詢通過select屬性配置度陆。

13、MyBatis實(shí)現(xiàn)一對(duì)多有幾種方式,怎么操作的献幔?

有聯(lián)合查詢和嵌套查詢懂傀。聯(lián)合查詢是幾個(gè)表聯(lián)合查詢,只查詢一次,通過在resultMap里面的collection節(jié)點(diǎn)配置一對(duì)多的類就可以完成;嵌套查詢是先查一個(gè)表,根據(jù)這個(gè)表里面的 結(jié)果的外鍵id,去再另外一個(gè)表里面查詢數(shù)據(jù),也是通過配置collection,但另外一個(gè)表的查詢通過select節(jié)點(diǎn)配置蜡感。

14蹬蚁、Mybatis是否支持延遲加載恃泪?如果支持,它的實(shí)現(xiàn)原理是什么缚忧?

答:Mybatis僅支持association關(guān)聯(lián)對(duì)象和collection關(guān)聯(lián)集合對(duì)象的延遲加載悟泵,association指的就是一對(duì)一,collection指的就是一對(duì)多查詢闪水。在Mybatis配置文件中糕非,可以配置是否啟用延遲加載lazyLoadingEnabled=true|false。

它的原理是球榆,使用CGLIB創(chuàng)建目標(biāo)對(duì)象的代理對(duì)象朽肥,當(dāng)調(diào)用目標(biāo)方法時(shí),進(jìn)入攔截器方法持钉,比如調(diào)用a.getB().getName()衡招,攔截器invoke()方法發(fā)現(xiàn)a.getB()是null值,那么就會(huì)單獨(dú)發(fā)送事先保存好的查詢關(guān)聯(lián)B對(duì)象的sql每强,把B查詢上來始腾,然后調(diào)用a.setB(b),于是a的對(duì)象b屬性就有值了空执,接著完成a.getB().getName()方法的調(diào)用浪箭。這就是延遲加載的基本原理。

當(dāng)然了辨绊,不光是Mybatis奶栖,幾乎所有的包括Hibernate,支持延遲加載的原理都是一樣的门坷。

15宣鄙、Mybatis的一級(jí)、二級(jí)緩存:

1)一級(jí)緩存: 基于 PerpetualCache 的 HashMap 本地緩存默蚌,其存儲(chǔ)作用域?yàn)?Session冻晤,當(dāng) Session flush 或 close 之后,該 Session 中的所有 Cache 就將清空绸吸,默認(rèn)打開一級(jí)緩存鼻弧。

2)二級(jí)緩存與一級(jí)緩存其機(jī)制相同,默認(rèn)也是采用 PerpetualCache惯裕,HashMap 存儲(chǔ)温数,不同在于其存儲(chǔ)作用域?yàn)?Mapper(Namespace),并且可自定義存儲(chǔ)源蜻势,如 Ehcache撑刺。默認(rèn)不打開二級(jí)緩存,要開啟二級(jí)緩存握玛,使用二級(jí)緩存屬性類需要實(shí)現(xiàn)Serializable序列化接口(可用來保存對(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冕屯。

16寂诱、什么是MyBatis的接口綁定?有哪些實(shí)現(xiàn)方式安聘?

接口綁定痰洒,就是在MyBatis中任意定義接口,然后把接口里面的方法和SQL語句綁定, 我們直接調(diào)用接口方法就可以,這樣比起原來了SqlSession提供的方法我們可以有更加靈活的選擇和設(shè)置。

接口綁定有兩種實(shí)現(xiàn)方式,一種是通過注解綁定浴韭,就是在接口的方法上面加上 @Select丘喻、@Update等注解,里面包含Sql語句來綁定念颈;另外一種就是通過xml里面寫SQL來綁定, 在這種情況下,要指定xml映射文件里面的namespace必須為接口的全路徑名泉粉。當(dāng)Sql語句比較簡單時(shí)候,用注解綁定, 當(dāng)SQL語句比較復(fù)雜時(shí)候,用xml綁定,一般用xml綁定的比較多。

17榴芳、使用MyBatis的mapper接口調(diào)用時(shí)有哪些要求嗡靡?

① Mapper接口方法名和mapper.xml中定義的每個(gè)sql的id相同;
② Mapper接口方法的輸入?yún)?shù)類型和mapper.xml中定義的每個(gè)sql 的parameterType的類型相同窟感;
③ Mapper接口方法的輸出參數(shù)類型和mapper.xml中定義的每個(gè)sql的resultType的類型相同讨彼;
④ Mapper.xml文件中的namespace即是mapper接口的類路徑。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末肌括,一起剝皮案震驚了整個(gè)濱河市点骑,隨后出現(xiàn)的幾起案子酣难,更是在濱河造成了極大的恐慌谍夭,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,039評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件憨募,死亡現(xiàn)場(chǎng)離奇詭異紧索,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)菜谣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門珠漂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人尾膊,你說我怎么就攤上這事媳危。” “怎么了冈敛?”我有些...
    開封第一講書人閱讀 165,417評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵待笑,是天一觀的道長。 經(jīng)常有香客問我抓谴,道長暮蹂,這世上最難降的妖魔是什么寞缝? 我笑而不...
    開封第一講書人閱讀 58,868評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮仰泻,結(jié)果婚禮上荆陆,老公的妹妹穿的比我還像新娘。我一直安慰自己集侯,他們只是感情好被啼,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著棠枉,像睡著了一般趟据。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上术健,一...
    開封第一講書人閱讀 51,692評(píng)論 1 305
  • 那天汹碱,我揣著相機(jī)與錄音,去河邊找鬼荞估。 笑死咳促,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的勘伺。 我是一名探鬼主播跪腹,決...
    沈念sama閱讀 40,416評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼飞醉!你這毒婦竟也來了冲茸?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,326評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤缅帘,失蹤者是張志新(化名)和其女友劉穎轴术,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體钦无,經(jīng)...
    沈念sama閱讀 45,782評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡逗栽,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了失暂。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片彼宠。...
    茶點(diǎn)故事閱讀 40,102評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖弟塞,靈堂內(nèi)的尸體忽然破棺而出凭峡,到底是詐尸還是另有隱情,我是刑警寧澤决记,帶...
    沈念sama閱讀 35,790評(píng)論 5 346
  • 正文 年R本政府宣布摧冀,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏按价。R本人自食惡果不足惜惭适,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望楼镐。 院中可真熱鬧癞志,春花似錦、人聲如沸框产。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽秉宿。三九已至戒突,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間描睦,已是汗流浹背膊存。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留忱叭,地道東北人隔崎。 一個(gè)月前我還...
    沈念sama閱讀 48,332評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像韵丑,于是被迫代替她去往敵國和親爵卒。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評(píng)論 2 355