模塊一_MyBatis模塊習(xí)題

序言:

文章內(nèi)容輸出來源:拉勾教育Java高薪訓(xùn)練營。
本篇文章是學(xué)習(xí)課程中的一部分課后筆記

自定義框架流程.png

一河质、自定義持久層框架Ipersistence是如何解決JDBC存在的問題?

    1. 使用配置文件解決硬編碼問題
    1. 使用C3P0連接池解決了頻繁創(chuàng)建釋放數(shù)據(jù)庫連接問題
    1. 在simpleExecute中使用了反射進(jìn)行了參數(shù)的設(shè)置
    1. 在simpleExecute中使用了內(nèi)省進(jìn)行返回結(jié)果集的封裝

二嘲碱、進(jìn)行自定義持久層框架Ipersistence優(yōu)化時(shí)主要為了解決哪些問題累奈?

    1. 應(yīng)用在Dao層,整個(gè)操作的模板代碼重復(fù)
    1. 調(diào)用sqlSession方法時(shí)彻桃、參數(shù)statementId硬編碼

三坛善、關(guān)于configuration 與 mappedStatement配置類的說法:

    1. 使用dom4j對(duì)sqlMapConfig.xml解析時(shí)會(huì)將解析出來的內(nèi)容以不同形式封裝到Configuration對(duì)象中
    1. 使用dom4j對(duì)mapper.xml解析時(shí),每一個(gè)<select>標(biāo)簽的內(nèi)容均對(duì)應(yīng)一個(gè)mappedStatement對(duì)象
    1. configuration 中包含了mappedStatement的引用

四邻眷、關(guān)于genericTokenParser類的說法:

    1. 該類只能通過有參構(gòu)造進(jìn)行創(chuàng)建
    1. genericTokenParser是通用的標(biāo)記解析類
    1. genericTokenParser在解析#{}占位符時(shí)必須通過標(biāo)記處理類tokenHandler的配合
    1. genericTokenParser三個(gè)構(gòu)造參數(shù)分別為開始標(biāo)記眠屎、結(jié)束標(biāo)記、標(biāo)記處理器

五肆饶、關(guān)于sqlessionFactoyBuilder改衩,sqlessionFactoy ,sqlession的說法:

    1. sqlessionFactoyBuilder最佳范圍為方法范圍驯镊,可定義為本地方法變量
    1. sqlessionFactoy 最佳范圍是應(yīng)用范圍
    1. sqlession最佳范圍是方法范圍或請(qǐng)求范圍

六葫督、關(guān)于resultType與入?yún)⒌恼f法:

    1. resultType表示返回值類型為:完整類名或別名竭鞍,允許使用基本數(shù)據(jù)類型,String橄镜、int等
    1. resultType和resultMap的數(shù)據(jù)結(jié)構(gòu)一樣的偎快,都是map結(jié)構(gòu)
    1. mybatis中,除了使用@param注解來實(shí)現(xiàn)多個(gè)參數(shù)入?yún)⑶⒔海€可以用Map對(duì)象實(shí)現(xiàn)多參數(shù)傳遞

七晒夹、mybatis中接口開發(fā)規(guī)范:

    1. mapper.xml中的namespace與mapper接口的類路徑相同
    1. mapper接口方法名和mapper.xml中定義的每個(gè)statement的id相同
    1. mapper接口方法的輸入?yún)?shù)類型和mapper.xml中定義的每個(gè)sql的parameterType類型相同
    1. mapper接口方法的輸出參數(shù)類型和mapper.xml中定義的每個(gè)sql的resultType類型相同

八、關(guān)于mybatis源碼內(nèi)容的說法:

    1. 涉及到的設(shè)計(jì)模式有:代理模式姊氓、builder模式丐怯、工廠模式、迭代器模式
    1. 功能架構(gòu)可以分為三層:接口層他膳、數(shù)據(jù)處理層响逢、框架支撐層
    1. 支持用插件對(duì)statementHandler、paramterHandle棕孙、resultsetHandler等核心對(duì)象進(jìn)行攔截
    1. Executor是執(zhí)行器,負(fù)債sql的生成和查詢緩存的維護(hù)
    1. statementtHandler封裝了jdbc statement操作些膨,負(fù)責(zé)對(duì)jdbc statement的操作
    1. typeHandler 負(fù)責(zé)java數(shù)據(jù)類型和jdbc數(shù)據(jù)類型之間的映射和轉(zhuǎn)換
    1. sqlSource 負(fù)責(zé)根據(jù)用戶傳遞的parameterObject動(dòng)態(tài)生產(chǎn)sql語句蟀俊,將信息封裝到boundsql對(duì)象中

九、Mybatis動(dòng)態(tài)sql是做什么的订雾?都有哪些動(dòng)態(tài)sql肢预?簡述一下動(dòng)態(tài)sql的執(zhí)行原理?

1.動(dòng)態(tài)sql:
  • 在數(shù)據(jù)庫執(zhí)行sql之前洼哎,需要對(duì)sql進(jìn)行整合處理烫映,根據(jù)傳入的參數(shù)值,以及匹配的條件噩峦,有可能需要?jiǎng)討B(tài)的去
    判斷是否為空锭沟,拼接sql。
2.動(dòng)態(tài)sql:

<where> 识补、 <if> 族淮、<include> 、<foreach>

<select id="selectUserByCondition" resultType="com.admin.entity.User">
        select
       <include refid="userInfo"/> 
        from
        user 
        <where> 
        <if test="name !=null and name !=''">
            and name = #{name }
        </if>
        <if test="roleIdList!=null and roleIdList.size() > 0 ">
            and role_id in
            <foreach collection="roleIdList" item="item" open="(" close=")" separator=",">
                #{item}
            </foreach>
        </if>
        </where>
</select>

map 入?yún)?/strong>

<select id="selectByMap" resultType="com.admin.entity.User">
  select * from user where
  <foreach collection="map" index="key" item="value"  separator="=">
    ${key} = #{value}
  </foreach>
</select>

<choose>凭涂、 <when>祝辣、 <otherwise>

<select id="selectUserInfo" resultType="com.admin.entity.User">
select * from user
 <where>
   <choose>
     <when test="name != null and name != ''">
       and name = #{name }
     </when>
     <otherwise>
       1 = 1
     </otherwise>
   </choose>
 </where>
</select>


<set>、 <trim>

<update id="updateUser" parameterType="com.admin.entity.User">
  update user
  <set>
    <if test="name != null and name != ''">
      name = #{name },
    </if>
  </set>
  where id = #{id}
</update>

<select id="selectUserByTrim" resultType="com.admin.entity.User">
  select * from user
  <trim prefix="where" suffix="order by id" prefixOverrides="and | or" suffixOverrides=",">
    <if test="name != null and name != ''">
      and name = #{name }
    </if>
    <if test="id != null and id !='' ">
      and id = #{id} 
    </if>
  </trim>
</select>


 -- 批量更新
<update id="updateUserInfoByList" parameterType="java.util.List">
        update user
        <trim prefix="set" suffixOverrides=",">
            <trim prefix="name =case" suffix="end,">
                <foreach collection="userList" item="item">
                    <if test="item.name!=null">
                        when id=#{item.id} then #{item.name}
                    </if>
                </foreach>
            </trim>
            <trim prefix="role_id =case" suffix="end,">
                <foreach collection="userList" item="item">
                    <if test="item.roleId!=null and item.roleId!=''">
                        when id=#{item.id} then #{item.roleId}
                    </if>
                </foreach>
            </trim>
        </trim>
        <where>
            <foreach collection="userList" separator="or" item="item">
                id = #{item.id}
            </foreach>
        </where>
    </update>

3.動(dòng)態(tài)sql的執(zhí)行原理:
  • MyBatis的動(dòng)態(tài)SQL是基于OGNL表達(dá)式切油。
  • 在解析xml配置文件的時(shí)候蝙斜,會(huì)有一個(gè)createSqlSource的操作。
  • createSqlSource底層使用了XMLScriptBuilder調(diào)用parseScriptNode()的方法澎胡,解析xml的標(biāo)簽孕荠。
  • 在parseScriptNode()的方法中有一個(gè)parseDynamicTags()方法娩鹉,會(huì)對(duì)nodeHandlers里的標(biāo)簽根據(jù)不同的handler來處理不同的標(biāo)簽 , 然后把DynamicContext結(jié)果放回SqlSource中岛琼。
  • 在Executor執(zhí)行的時(shí)候底循,調(diào)用DynamicSqlSource的解析方法,并返回解析好的BoundSql槐瑞,排好序熙涤,替換好參數(shù)的sql。

十困檩、Mybatis是否支持延遲加載祠挫?如果支持,它的實(shí)現(xiàn)原理是什么悼沿?

1.Mybatis支持延遲加載
  • 僅支持 association 關(guān)聯(lián)對(duì)象和 collection 關(guān)聯(lián)集合對(duì)象的延遲加載等舔;
  • association 指的是一對(duì)一,collection 指的是一對(duì)多查詢糟趾。
  • 配置文件中慌植,可以配置是否啟用延遲加載 lazyLoadingEnabled=true|false。
<settings>
    <!-- 打開延遲加載的開關(guān) -->
    <setting name="lazyLoadingEnabled" value="true"/>
    <!-- 將積極加載改為消極加載义郑,即延遲加載 -->
    <setting name="aggressiveLazyLoading" value="false"/>
</settings>
2.實(shí)現(xiàn)原理
  • 使用 CGLIB 創(chuàng)建目標(biāo)對(duì)象的代理對(duì)象蝶柿,當(dāng)調(diào)用目標(biāo)方法時(shí),進(jìn)入攔
    截器方法非驮,當(dāng)數(shù)據(jù)需要的時(shí)候在調(diào)用sql查詢DB交汤。
  • 例如 : 調(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)用。

十一栋盹、Mybatis都有哪些Executor執(zhí)行器施逾?它們之間的區(qū)別是什么?

1.三種Executor:
  • SimpleExecutor 例获、ReuseExecutor 汉额、 BatchExecutor
2.區(qū)別
  • SimpleExecutor:每執(zhí)行一次update或select,就開啟一個(gè)Statement對(duì)象榨汤,用完立刻關(guān)閉Statement對(duì)象蠕搜。

  • ReuseExecutor:執(zhí)行update或select,以sql作為key查找Statement對(duì)象收壕,存在就使用妓灌,不存在就創(chuàng)建轨蛤,用完后,不關(guān)閉Statement對(duì)象虫埂,而是放置于Map內(nèi)祥山,供下一次使用。
    簡言之掉伏,就是重復(fù)使用Statement對(duì)象缝呕。

  • BatchExecutor:執(zhí)行update(沒有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)墓塌。

  • 在Mybatis配置文件中色迂,可以指定默認(rèn)的ExecutorType執(zhí)行器類型新博,也可以手動(dòng)給DefaultSqlSessionFactory的創(chuàng)建SqlSession的方法傳遞ExecutorType類型參數(shù)。

十二脚草、簡述下Mybatis的一級(jí)、二級(jí)緩存(分別從存儲(chǔ)結(jié)構(gòu)原献、范圍馏慨、失效場(chǎng)景。三個(gè)方面來作答)姑隅?

1.存儲(chǔ)結(jié)構(gòu):
  • 一級(jí)緩存写隶、二級(jí)緩存都是緩存到HashMap結(jié)構(gòu)中。
2.范圍:
  • 一級(jí)緩存SqlSession級(jí)別的讲仰,作用域是SqlSession慕趴,Mybatis默認(rèn)開啟一級(jí)緩存,在同一個(gè)SqlSession中鄙陡,相同的Sql查詢的時(shí)候冕房,第一次查詢的時(shí)候,就會(huì)從緩存中取趁矾,如果發(fā)現(xiàn)沒有數(shù)據(jù)耙册,那么就從DB查詢出來,并且緩存到HashMap中毫捣,第二次查詢直接在緩存中取详拙,有數(shù)據(jù)就直接返回帝际,不查DB。

  • 二級(jí)緩存mapper級(jí)別的饶辙,多個(gè)SqlSession去操作同一個(gè)mapper的sql語句蹲诀,多個(gè)SqlSession可以共用二級(jí)緩存,二級(jí)緩存是跨SqlSession弃揽。
    第一次調(diào)用mapper下的sql 的時(shí)候去查詢信息脯爪,查詢到的信息會(huì)存放到該mapper對(duì)應(yīng)的二級(jí)緩存區(qū)域,第二次調(diào)用namespace下的mapper映射文件中蹋宦,相同的SQL去查詢披粟,直接在二級(jí)緩存內(nèi)取結(jié)果。

3.失效場(chǎng)景:
  • 一級(jí)緩存 當(dāng)進(jìn)行增刪改的操作的時(shí)候冷冗,緩存將會(huì)失效守屉。
    在spring容器管理中每次查詢都是創(chuàng)建一個(gè)新的sqlSession,所以在分布式環(huán)境中不會(huì)出現(xiàn)數(shù)據(jù)不一致的問題蒿辙。

  • 二級(jí)緩存 使用時(shí)需要開啟cache標(biāo)簽拇泛,在select上添加useCache屬性為true,
    更新和刪除時(shí)候需要手動(dòng)開啟flushCache刷新緩存思灌。

十三俺叭、簡述Mybatis的插件運(yùn)行原理,以及如何編寫一個(gè)插件泰偿?

1.運(yùn)行原理:
  • mybatis可以編寫針對(duì)Executor熄守、StatementHandler、ParameterHandler耗跛、ResultSetHandler四個(gè)接口的插件裕照,mybatis使用JDK的動(dòng)態(tài)代理為需要攔截的接口生成代理對(duì)象,然后實(shí)現(xiàn)接口的攔截方法调塌,所以當(dāng)執(zhí)行需要攔截的接口方法時(shí)晋南,會(huì)進(jìn)入攔截方法(AOP思想)。
2.如何編寫:
  • 1.編寫Intercepror接口的實(shí)現(xiàn)類

  • 2.設(shè)置插件的簽名羔砾,告訴mybatis攔截哪個(gè)對(duì)象的哪個(gè)方法

  • 3.最后將插件注冊(cè)到全局配置文件中

  • 示例:

//插件簽名负间,告訴mybatis當(dāng)前插件攔截哪個(gè)對(duì)象的哪個(gè)方法
//type表示要攔截的目標(biāo)對(duì)象,method表示要攔截的方法姜凄,args表示要攔截方法的參數(shù)
@Intercepts({
    @Signature(type=StatementHandler.class,method="parameterize",args=java.sql.Statement.class)
})
public class MySecondPlugin implements Interceptor {

    //攔截目標(biāo)對(duì)象的目標(biāo)方法執(zhí)行
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        System.out.println("MySecondPlugin攔截目標(biāo)對(duì)象:"+invocation.getTarget()+"的目標(biāo)方法:"+invocation.getMethod());
        
        /*
         * 插件的主要功能:在執(zhí)行目標(biāo)方法之前政溃,可以對(duì)sql進(jìn)行修改已完成特定的功能
         * 例如增加分頁功能,實(shí)際就是給sql語句添加limit檀葛;還有其他等等操作都可以
         * */
        
        //執(zhí)行目標(biāo)方法
        Object proceed = invocation.proceed();
        //返回執(zhí)行后的返回值
        return proceed;
    }
    //包裝目標(biāo)對(duì)象:為目標(biāo)對(duì)象創(chuàng)建代理對(duì)象
    @Override
    public Object plugin(Object target) {
        System.out.println("MySecondPlugin為目標(biāo)對(duì)象"+target+"創(chuàng)建代理對(duì)象");
        //this表示當(dāng)前攔截器玩祟,target表示目標(biāo)對(duì)象,wrap方法利用mybatis封裝的方法為目標(biāo)對(duì)象創(chuàng)建代理對(duì)象(沒有攔截的對(duì)象會(huì)直接返回屿聋,不會(huì)創(chuàng)建代理對(duì)象)
        Object wrap = Plugin.wrap(target, this);
        return wrap;
    }
    //設(shè)置插件在配置文件中配置的參數(shù)值
    @Override
    public void setProperties(Properties properties) {
        System.out.println("MySecondPlugin配置的參數(shù):"+properties);
    }

}

  • 插件注冊(cè)到全局配置文件中
<plugins>
    <plugin interceptor="com.mybatis_demo.plugin.MySecondPlugin"></plugin>
</plugins>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末空扎,一起剝皮案震驚了整個(gè)濱河市藏鹊,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌转锈,老刑警劉巖盘寡,帶你破解...
    沈念sama閱讀 217,826評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異撮慨,居然都是意外死亡竿痰,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門砌溺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來影涉,“玉大人,你說我怎么就攤上這事规伐⌒非悖” “怎么了?”我有些...
    開封第一講書人閱讀 164,234評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵猖闪,是天一觀的道長鲜棠。 經(jīng)常有香客問我,道長培慌,這世上最難降的妖魔是什么豁陆? 我笑而不...
    開封第一講書人閱讀 58,562評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮吵护,結(jié)果婚禮上盒音,老公的妹妹穿的比我還像新娘。我一直安慰自己馅而,他們只是感情好里逆,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著用爪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪胁镐。 梳的紋絲不亂的頭發(fā)上偎血,一...
    開封第一講書人閱讀 51,482評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音盯漂,去河邊找鬼颇玷。 笑死,一個(gè)胖子當(dāng)著我的面吹牛就缆,可吹牛的內(nèi)容都是我干的帖渠。 我是一名探鬼主播,決...
    沈念sama閱讀 40,271評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼竭宰,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼空郊!你這毒婦竟也來了份招?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,166評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤狞甚,失蹤者是張志新(化名)和其女友劉穎锁摔,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體哼审,經(jīng)...
    沈念sama閱讀 45,608評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡谐腰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了涩盾。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片十气。...
    茶點(diǎn)故事閱讀 39,926評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖春霍,靈堂內(nèi)的尸體忽然破棺而出砸西,到底是詐尸還是另有隱情,我是刑警寧澤终畅,帶...
    沈念sama閱讀 35,644評(píng)論 5 346
  • 正文 年R本政府宣布籍胯,位于F島的核電站,受9級(jí)特大地震影響离福,放射性物質(zhì)發(fā)生泄漏杖狼。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評(píng)論 3 329
  • 文/蒙蒙 一妖爷、第九天 我趴在偏房一處隱蔽的房頂上張望蝶涩。 院中可真熱鬧,春花似錦絮识、人聲如沸绿聘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽熄攘。三九已至,卻和暖如春彼念,著一層夾襖步出監(jiān)牢的瞬間挪圾,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評(píng)論 1 269
  • 我被黑心中介騙來泰國打工逐沙, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留哲思,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,063評(píng)論 3 370
  • 正文 我出身青樓吩案,卻偏偏與公主長得像棚赔,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評(píng)論 2 354