<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>

          不懂SqlSession,你還說你會(huì)Mybatis?

          共 4889字,需瀏覽 10分鐘

           ·

          2021-08-19 12:48

          本篇文章開始之前,我們先看看各大互聯(lián)網(wǎng)公司的Java招聘要求:

          其實(shí)都對(duì)Mybatis有一定的要求,如何深入理解 Mybatis呢?

          上一篇文章中,我們介紹了 SqlSessionFactory 的創(chuàng)建過程,忘記了的,可以回顧一下,或者看下面這張圖也行。

          接下來,可樂講給大家介紹 Mybatis 中另一個(gè)重量級(jí)嘉賓——SqlSession,有了這個(gè)對(duì)象,我們就能對(duì)數(shù)據(jù)進(jìn)行一頓操作了。理解了這個(gè)類的創(chuàng)建過程,我相信對(duì)于 Mybatis 的核心架構(gòu),你就清楚了。大家伙小板凳搬起來,請(qǐng)看可樂為大家一一道來。

          1、實(shí)例代碼

          在實(shí)例搭建文章中,通過 SqlSession 對(duì)象查詢數(shù)據(jù),可樂寫了兩種方法。

          ①、常規(guī)的需要我們拼接 statement 方式;

          ②、xxxMapper.interface 接口代理方式;

          對(duì)應(yīng)下面兩種方法:

          //根據(jù)id查詢person表數(shù)據(jù)
          @Test
          public void testSelectPersonById() {
              /*這個(gè)字符串由 PersonMapper.xml 文件中 兩個(gè)部分構(gòu)成
                  <mapper namespace="com.itcoke.mapper.PersonMapper"> 的 namespace 的值
                  <select id="selectPersonById" > id 值
              */

              String namespace = "com.itcoke.mapper.PersonMapper";
              String method = "selectPersonById";
              //根據(jù) sqlSessionFactory 產(chǎn)生 session
              SqlSession sqlSession = sessionFactory.openSession();
              Person person = sqlSession.selectOne(namespace + "." + method, 1L);
              System.out.println(person);
              sqlSession.close();
          }


          //根據(jù)id查詢person表數(shù)據(jù)
          //通過接口代理的方式
          @Test
          public void testInterfaceSelectPersonById() {
              //根據(jù) sqlSessionFactory 產(chǎn)生 session
              SqlSession sqlSession = sessionFactory.openSession();
              PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);
              Person person = mapper.selectPersonById(1L);
              System.out.println(person);
              sqlSession.close();
          }

          本篇文章可樂講給大家介紹第一種原生方式,其實(shí)第二種接口代理最后也是走的第一種方式,這個(gè)我們下篇文章具體介紹。

          2、構(gòu)建過程圖示

          3、代碼剖析

          3.1 Executor

          我們通過 DefaultSessionFactory.openSession() 方法獲取 sqlSession

          其實(shí)是可以通過構(gòu)造方法指定 Executor 的類型,比如:

          SqlSession sqlSession = sessionFactory.openSession(ExecutorType.SIMPLE);

          再看生成 Executor 的源代碼:

          如果不指定執(zhí)行器類型,直接默認(rèn) openSession() 方法,生成的是 CachingExecutor 執(zhí)行器,這里的 cacheEnabled 其實(shí)是默認(rèn)開啟二級(jí)緩存的配置,在 mybatis-config.xml 文件中.

          并且需要注意的是這里 new CachingExecutor(executor),傳進(jìn)去了一個(gè) SimpleExecutor 對(duì)象,后面和數(shù)據(jù)庫交互的實(shí)際上是該對(duì)象。

          得到了 SqlSession,接下來看這段代碼:

          Person person = sqlSession.selectOne(namespace + "." + method, 1L);

          直接看上面源碼的第 76 行代碼:

          List<T> list = this.selectList(statement, parameter);

          在上一篇文章介紹 SqlSessionFactory 的構(gòu)建過程時(shí),我們說了 configuration 對(duì)象的組成:

          看上面的源碼得到 MappedStatement 對(duì)象,包含了我們?cè)?mapper.xml 文件中配置的 sql 語句。

          執(zhí)行 executor.query() 方法,注意,這里的 executor 是 CachingExecutor:

          這段源碼,我們可以得到兩個(gè)信息:

          ①、獲取我們指定配置的boundSql 對(duì)象,包含我們配置的 sql 語句和參數(shù)信息。

          ②、根據(jù)相關(guān)信息得到一個(gè)緩存 key,通過這個(gè)key,連續(xù)兩次相同的查詢,第二次可以不去查數(shù)據(jù)庫,直接獲取緩存的數(shù)據(jù)。

          接著我們繼續(xù)看 query() 方法:

          看源碼,也就是說先去查緩存,緩存命中了直接返回?cái)?shù)據(jù),沒有命中就執(zhí)行:delegate.query() 方法。

          這里的 delegate 是上文我們說的構(gòu)造 Executor 傳進(jìn)來得 SimpleExecutor 對(duì)象。

          關(guān)于 mybatis 緩存后面可樂會(huì)專門寫一篇文章來仔細(xì)介紹,這里我們先梳理主線,看上面第 156 行代碼,緩存查不到,從數(shù)據(jù)庫里面查。

          繼續(xù)跟 queryFromDatabase() 方法:

          3.2 StatementHandler

          執(zhí)行到上面第 61 行源碼:

          StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);

          跟進(jìn)去:

          這里構(gòu)造的是一個(gè) RoutingStatementHandler 對(duì)象,聰明的你一聽聽名字都知道會(huì)路由生成別的對(duì)象。

          沒錯(cuò),是根據(jù)傳入的 statementType 生成具體的對(duì)象:

          在 MappedStatement 對(duì)象中,默認(rèn) statementType 是 PERPARED:

          也就是這里最終生成的 StatementHandler 實(shí)際上是 PreparedStatementHandler 對(duì)象。

          通常情況下:

          ①、不帶參數(shù)的 SQL語句執(zhí)行,會(huì)生成 SimpleStatementHandler 對(duì)象。

          ②、帶參數(shù)的 SQL 語句執(zhí)行,會(huì)生成 PreparedStatementHandler 對(duì)象。

          ③、存儲(chǔ)過程執(zhí)行,會(huì)生成 CallableStatementHandler 對(duì)象。

          3.3 ParameterHandler

          再回到 SimpleExecutor 的 doQuery() 方法:

          看第 62 行代碼:

          stmt = prepareStatement(handler, ms.getStatementLog());

          跟進(jìn)去:

          這里第 86 行獲取數(shù)據(jù)庫連接。

          第 88 行,進(jìn)行參數(shù)處理,說直接點(diǎn),就是將 SQL 語句中的 “?” 替換成我們傳入的具體值。

          但是我們知道 Java對(duì)象參數(shù)和數(shù)據(jù)庫參數(shù)是不一樣的,那么肯定還會(huì)做參數(shù)類型轉(zhuǎn)換,沒錯(cuò),就是通過下面將要介紹 TypeHandler 來完成。

          3.4 TypeHandler

          也就是將 Java 類型和 數(shù)據(jù)庫類型進(jìn)行互相轉(zhuǎn)換。

          Mybatis 提供給了很多內(nèi)置的參數(shù)轉(zhuǎn)換,基本上不需要我們自己去定義。

          當(dāng)然,聰明的你可能會(huì)問了,假如這些都不滿足呢?假如我要自定義一些類型呢?

          不用擔(dān)心,Mybatis 給我們預(yù)留了自定義類型的接口,如果你想自定義類型,通常分為兩步:

          ①、實(shí)現(xiàn) org.apache.ibatis.type.TypeHandler 接口, 或繼承類 org.apache.ibatis.type.BaseTypeHandler

          ②、在配置文件中配置自定義的 TypeHnadler。

          這里可樂就不做詳細(xì)描述了,官網(wǎng)寫的也很清楚:

          https://mybatis.org/mybatis-3/zh/configuration.html#typeHandlers

          3.4 ResultSetHandler

          還是回到 SimpleExecutor 的 doQuery() 方法:

          上一步我們得到了 PrepraedStatementHandler 對(duì)象,接著看 handler.query() 方法:

          通過執(zhí)行 ps.execute() 方法,得到結(jié)果集,然后通過 resultSetHandler 去處理結(jié)果集。

          4、總結(jié)

          這樣,可樂就給大家完整的講解了如何通過 SqlSession 進(jìn)行一次數(shù)據(jù)庫查詢操作,但是正如文章開頭所言,可樂給大家介紹了兩種查詢方式,一種是需要自己拼接 namespace+method 語句,另一種是通過 接口的形式。其實(shí)這兩種方式是一樣的,namespace 就是接口的包名(對(duì)應(yīng)xxxMapper.xml 的namespace名稱),method 就是接口的方法名(對(duì)應(yīng)到xxxMapper.xml 的每個(gè)SQL語句的 id 屬性),通過兩者拼接,我們能去 xxxMapper.xml 文件中定位到具體的 SQL 語句。

          很明顯,通過接口的形式避免了我們寫字符串錯(cuò)誤的可能,實(shí)際開發(fā)中,我們基本上都是這種方式,下一篇文章,可樂將給大家揭秘這種方式的奧秘。


          瀏覽 53
          點(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>
                  大香蕉乱伦网 | 国产18第一无限资源网站 | 网红鹿少女演绎点外卖视频 | 99精品在线观看免费视频 | 黄色艹比视频网站 |