<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          面試難點(diǎn):Mybatis 中的 DAO 接口和 XML 文件里的 SQL 是如何建立關(guān)系的?

          共 3030字,需瀏覽 7分鐘

           ·

          2022-08-25 18:33

          點(diǎn)擊關(guān)注公眾號(hào),Java干貨及時(shí)送達(dá)

          作者:張維鵬

          來源:blog.csdn.net/a745233700/article/details/89308762

          一、解析XML:

          首先,Mybatis 在初始化SqlSessionFactoryBean時(shí),會(huì)找到mapperLocations配置的路徑下中所有的XML文件并進(jìn)行解析,這里我們重點(diǎn)關(guān)注兩部分:

          1、創(chuàng)建SqlSource:

          Mybatis會(huì)把每個(gè)SQL標(biāo)簽封裝成SqlSource對(duì)象,然后根據(jù)SQL語句的不同,又分為動(dòng)態(tài)SQL和靜態(tài)SQL。其中,靜態(tài)SQL包含一段String類型的sql語句;而動(dòng)態(tài)SQL則是由一個(gè)個(gè)SqlNode組成。


          假如我們有這樣一個(gè)SQL:

          <select id="getUserById" resultType="user">
              select * from user 
              <where>
                  <if test="uid!=null">
                      and uid=#{uid}
                  </if>
              </where>
          </select>    
          它對(duì)應(yīng)的SqlSource對(duì)象看起來應(yīng)該是這樣的:

          2、創(chuàng)建MappedStatement:

          接下來,Mybatis會(huì)為XML中的每個(gè)SQL標(biāo)簽都生成一個(gè)MappedStatement對(duì)象,這里面有兩個(gè)屬性很重要:
          • id:全限定類名+方法名組成的ID
          • sqlSource:當(dāng)前SQL標(biāo)簽對(duì)應(yīng)的SqlSource對(duì)象
          創(chuàng)建完的MappedStatement對(duì)象會(huì)被添加到Configuration中,Configuration對(duì)象就是Mybatis中的大管家,基本所有的配置信息都維護(hù)在這里。當(dāng)把所有的XML都解析完成之后,Configuration就包含了所有的SQL信息。

          到目前為止,XML就解析完成了,當(dāng)我們執(zhí)行Mybatis方法的時(shí)候,就可以通過 “全限定類名+方法名” 找到MappedStatement對(duì)象,然后解析里面的SQL內(nèi)容并進(jìn)行執(zhí)行即可。

          二、Dao接口代理:

          但是Dao接口并沒有具體的實(shí)現(xiàn)類,那么在被調(diào)用時(shí),最終又是怎樣找到我們的SQL語句的呢?
          首先,我們?cè)赟pring配置文件中,一般會(huì)這樣配置:
          <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
           <property name="basePackage" value="com.viewscenes.netsupervisor.dao" />
           <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
          </bean>
          或者你的項(xiàng)目是基于SpringBoot的,那么肯定也見過這種:@MapperScan("com.xxx.dao")
          它們的作用是一樣的,就是將包路徑下的所有類注冊(cè)到 Spring Bean 中,并將它們的beanClass設(shè)置為MapperFactoryBeanMapperFactoryBean實(shí)現(xiàn)了FactoryBean接口,俗稱工廠Bean。那么,當(dāng)我們通過@Autowired注入這個(gè)Dao接口時(shí),返回的對(duì)象就是MapperFactoryBean這個(gè)工廠Bean中的getObject()方法對(duì)象。
          那么,這個(gè)方法干了些什么呢?簡單來說,它就是通過JDK動(dòng)態(tài)代理,返回了一個(gè)Dao接口的代理對(duì)象MapperProxy,當(dāng)我們通過@Autowired注入Dao接口時(shí),注入的就是這個(gè)代理對(duì)象,我們調(diào)用 Dao接口中的方法時(shí),則會(huì)調(diào)用到MapperProxy對(duì)象的invoke()方法。
          那么,目前為止,我們通過Dao接口也有了代理實(shí)現(xiàn),所以就可以執(zhí)行到它里面的方法了。

          三、執(zhí)行:

          如上所述,當(dāng)我們調(diào)用Dao接口方法的時(shí)候,實(shí)際調(diào)用到代理對(duì)象的invoke()方法。在這里,實(shí)際上調(diào)用的就是SqlSession里面的東西了。
          public class DefaultSqlSession implements SqlSession {
           public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
            try {
             MappedStatement ms = configuration.getMappedStatement(statement);
             return executor.query(ms, 
              wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
            }
           }
          }
          看到以上代碼,說明我們想的不錯(cuò)。它就是通過statement(全限定類型+方法名)拿到MappedStatement對(duì)象,然后通過執(zhí)行器Executor去執(zhí)行具體SQL并返回。

          四、總結(jié)

          1、針對(duì)Mybatis中的Dao接口和XML文件里的SQL是如何建立關(guān)系的問題,主要可以歸納為下面幾點(diǎn)小點(diǎn):
          • SqlSource以及動(dòng)態(tài)標(biāo)簽SqlNode
          • MappedStatement對(duì)象
          • Spring工廠Bean以及動(dòng)態(tài)代理
          • SqlSession以及執(zhí)行器
          2、針對(duì)有兩個(gè)XML文件和這個(gè)Dao建立關(guān)系是否會(huì)沖突的問題:不管有幾個(gè)XML和Dao建立關(guān)系,只要保證namespace+id唯一即可。

              

          1、社區(qū)糾紛不斷:程序員何苦為難程序員?

          2、該死的單元測(cè)試,寫起來到底有多痛?

          3、互聯(lián)網(wǎng)人為什么學(xué)不會(huì)擺爛

          4、為什么國外JetBrains做 IDE 就可以養(yǎng)活自己,國內(nèi)不行?區(qū)別在哪?

          5、相比高人氣的Rust、Go,為何 Java、C 在工具層面進(jìn)展緩慢?

          6、讓程序員早點(diǎn)下班的《技術(shù)寫作指南》

          點(diǎn)

          點(diǎn)

          點(diǎn)點(diǎn)

          點(diǎn)在看

          瀏覽 44
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  翔田千里成人AV片 | 久久无码高清视频 | 无码免费一区二区三区在线 | 一级内射片在线网站观看 | A片一A片 |