亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專(zhuān)欄INFORMATION COLUMN

mybatis sqlSession的運(yùn)行過(guò)程

BoYang / 2088人閱讀

摘要:在找那個(gè)可以根據(jù)中的屬性,確定類(lèi)的全限定類(lèi)名。并且根據(jù)節(jié)點(diǎn)所對(duì)應(yīng)的,找到所要執(zhí)行的方法。因?yàn)樗鶕?jù)的是類(lèi)名方法名進(jìn)行唯一確定節(jié)點(diǎn)的。

當(dāng)我們使用sqlSession.getMapper(xx.class)方法時(shí),Mybatis其實(shí)是使用了jdk的動(dòng)態(tài)代理技術(shù),在MapperProxyFactory中生成對(duì)應(yīng)的Mapper對(duì)象。

這段是MappedProxyFactory中的一段代碼

protected T newInstance(MapperProxy mapperProxy) {
        return Proxy.newProxyInstance(this.mapperInterface.getClassLoader(), new Class[]{this.mapperInterface}, mapperProxy);
    }

其中mapperProxy對(duì)應(yīng)的是MapperProxy,該類(lèi)實(shí)現(xiàn)了InvocationHanlder接口。
正如我們所知,JDK的動(dòng)態(tài)代理是根據(jù)接口來(lái)生成代理對(duì)象的。在Mybatis找那個(gè)可以根據(jù)Mapper.xml中的namespace屬性,確定類(lèi)的全限定類(lèi)名。并且根據(jù)節(jié)點(diǎn)(insert | select | update | delete)所對(duì)應(yīng)的ID,找到所要執(zhí)行的方法。也因此,Mybatis中的方法是不能重載的。因?yàn)樗鶕?jù)的是類(lèi)名+方法名進(jìn)行唯一確定MapperStatement(節(jié)點(diǎn))的。

這個(gè)就是MapperStatement所封裝的一些信息了

再接著,當(dāng)我們調(diào)用Mapper對(duì)應(yīng)的方法時(shí),此時(shí),會(huì)交給代理對(duì)象進(jìn)行處理。
MapperProxy#的invoke

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if(Object.class.equals(method.getDeclaringClass())) {
            try {
                return method.invoke(this, args);
            } catch (Throwable var5) {
                throw ExceptionUtil.unwrapThrowable(var5);
            }
        } else {
        //執(zhí)行到這一步,如果方法是第一次調(diào)用,那么會(huì)創(chuàng)建對(duì)象,如果不是則使用緩存
        //需要注意的是調(diào)用的cacheMapperMethod方法,其實(shí)就是用一個(gè)Map進(jìn)行緩存                        
            MapperMethod mapperMethod = this.cachedMapperMethod(method);
            return mapperMethod.execute(this.sqlSession, args);
        }
    }

緊接著,調(diào)用了MapperMethod#execute(this,sqlSession,args);
這個(gè)方法比較簡(jiǎn)單,就是根據(jù)節(jié)點(diǎn)的類(lèi)型,進(jìn)行相應(yīng)的處理。比如節(jié)點(diǎn)是insert 那就走到insert的邏輯,其他類(lèi)似了。。。

本人的節(jié)點(diǎn)類(lèi)型是select,方法返回值是list,所以代碼執(zhí)行了這個(gè)方法

private  Object executeForMany(SqlSession sqlSession, Object[] args) {
        Object param = this.method.convertArgsToSqlCommandParam(args);
        List result;
        if(this.method.hasRowBounds()) {
            RowBounds rowBounds = this.method.extractRowBounds(args);
            result = sqlSession.selectList(this.command.getName(), param, rowBounds);
        } else {
            result = sqlSession.selectList(this.command.getName(), param);
        }

        return !this.method.getReturnType().isAssignableFrom(result.getClass())?(this.method.getReturnType().isArray()?this.convertToArray(result):this.convertToDeclaredCollection(sqlSession.getConfiguration(), result)):result;
    }

這里看到方法還執(zhí)行了convertArgsToSqlCommandParam(args)方法,這個(gè)方法返回的對(duì)象值如下。其實(shí)說(shuō)白了,就是對(duì)我們傳進(jìn)去參數(shù)的封裝。需要注意到,這邊其實(shí)是個(gè)Map對(duì)象,因?yàn)槲业腗apper接口的方法是使用@Param注解的形式的。如果你傳進(jìn)去的是個(gè)POJO或者M(jìn)ap,那么這邊就是POJO或者M(jìn)ap,如果是基本數(shù)據(jù)類(lèi)型(單個(gè)值),那么會(huì)被轉(zhuǎn)換成包裝數(shù)據(jù)類(lèi)型

中間的有些步驟就省略了。接下里的話,會(huì)將于需要執(zhí)行的對(duì)象的方法,sql,sql參數(shù)創(chuàng)建一個(gè)緩存key
.

然后調(diào)用CacheExecutor#query,根據(jù)key查詢(xún)有沒(méi)有緩存,如果有緩存,直接從緩存中拿,如果沒(méi)有,則繼續(xù)執(zhí)行。

期間會(huì)調(diào)用一個(gè)比較重要的方法 BaseExecutor#queryFromDatabase

private  List queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
        this.localCache.putObject(key, ExecutionPlaceholder.EXECUTION_PLACEHOLDER);  //key其實(shí)就是之前提到過(guò)的CacheKey,value只是充當(dāng)一個(gè)占位。。

        List list;
        try {
            list = this.doQuery(ms, parameter, rowBounds, resultHandler, boundSql);  //代碼執(zhí)行到這里。。。
        } finally {
            this.localCache.removeObject(key);
        }

        this.localCache.putObject(key, list);
        if(ms.getStatementType() == StatementType.CALLABLE) {
            this.localOutputParameterCache.putObject(key, parameter);
        }

        return list;
    }

下面就是比較關(guān)鍵的地方了
代碼執(zhí)行了simpleExecutor#doQuery

 public  List doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
        Statement stmt = null;

        List var9;
        try {
            Configuration configuration = ms.getConfiguration();
            StatementHandler handler = configuration.newStatementHandler(this.wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
            stmt = this.prepareStatement(handler, ms.getStatementLog());
            var9 = handler.query(stmt, resultHandler);
        } finally {
            this.closeStatement(stmt);
        }

        return var9;
    }

從這邊可以看出在Executor內(nèi)創(chuàng)建了StatementHandler,并對(duì)參數(shù)進(jìn)行了預(yù)處理,而調(diào)用的handler.query()方法后,var9的值,就是我們所要查詢(xún)的結(jié)果了。

值得一提的是StatementHandler有4個(gè)默認(rèn)的實(shí)現(xiàn)類(lèi):
RoutingStatementHandler:這是一個(gè)封裝類(lèi),不提供具體的實(shí)現(xiàn),根據(jù)Executor的類(lèi)型,創(chuàng)建不同的類(lèi)型的StatementHandler
SimpleStatementHandler:這個(gè)類(lèi)對(duì)應(yīng)于JDBC的Statement對(duì)象,用于沒(méi)有預(yù)編譯參數(shù)的SQL的運(yùn)行
PreparedStatementHandler:用于預(yù)編譯參數(shù)SQL的運(yùn)行
CallableStatementHandler:用于存儲(chǔ)過(guò)程的調(diào)度

在newStatementHandler方法中,我們也可以看到是創(chuàng)建了RoutingStatementHandler對(duì)象,會(huì)根據(jù)具體的Executor類(lèi)型,創(chuàng)建不同的StatementHandler。而這個(gè)具體的StatementHandler被存儲(chǔ)在了RoutingStatementHandler的delegate屬性中

先看configuration#newStatementHandler。注意到這邊有個(gè)interceptorChain.pluginAll 這邊就是用來(lái)執(zhí)行插件的。

public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
        StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
        StatementHandler statementHandler = (StatementHandler)this.interceptorChain.pluginAll(statementHandler);
        return statementHandler;
}

這個(gè)是所創(chuàng)建的StatementHandler所包含的信息,可以看到包含了很多東西

再來(lái)看simpleExecutor#prepareStatement

private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
        Connection connection = this.getConnection(statementLog); // 在此處獲取了數(shù)據(jù)的連接,此對(duì)象是個(gè)包裝對(duì)象,包裝了JDBC的Connection
        Statement stmt = handler.prepare(connection);  // 這邊是進(jìn)行一些預(yù)處理
        handler.parameterize(stmt);  
        return stmt;
    }

這邊的調(diào)用的parameterize的方法就是對(duì)參數(shù)進(jìn)行預(yù)處理了。其實(shí)就是遍歷parameterMappings集合,然后從里面取出參數(shù)的屬性,對(duì)參數(shù)進(jìn)行處理,這個(gè)就是這個(gè)方法的邏輯。(注:parameterMappings 集合中存放的是傳遞進(jìn)來(lái)的參數(shù)的屬性)

當(dāng)查詢(xún)到結(jié)果到時(shí)候,會(huì)調(diào)用DefaultResultSetHandler對(duì)結(jié)果進(jìn)行包裝。并且查詢(xún)完結(jié)果后,會(huì)將結(jié)果放到緩存中去

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/67751.html

相關(guān)文章

  • 【深入淺出MyBatis筆記】MyBatis解析和運(yùn)行原理

    摘要:的解析和運(yùn)行原理構(gòu)建過(guò)程提供創(chuàng)建的核心接口。在構(gòu)造器初始化時(shí)會(huì)根據(jù)和的方法解析為命令。數(shù)據(jù)庫(kù)會(huì)話器定義了一個(gè)對(duì)象的適配器,它是一個(gè)接口對(duì)象,構(gòu)造器根據(jù)配置來(lái)適配對(duì)應(yīng)的對(duì)象。它的作用是給實(shí)現(xiàn)類(lèi)對(duì)象的使用提供一個(gè)統(tǒng)一簡(jiǎn)易的使用適配器。 MyBatis的解析和運(yùn)行原理 構(gòu)建SqlSessionFactory過(guò)程 SqlSessionFactory提供創(chuàng)建MyBatis的核心接口SqlSess...

    bitkylin 評(píng)論0 收藏0
  • MyBatis原理概括

    摘要:避免了幾乎所有的代碼和手動(dòng)設(shè)置參數(shù)以及獲取結(jié)果集。這個(gè)對(duì)象主要是獲取方法對(duì)應(yīng)的命令和執(zhí)行相應(yīng)操作等的處理,具體細(xì)節(jié)同學(xué)們可以抽空研究。所以這里的方法主要使用了和對(duì)象幫助我們處理語(yǔ)句集和參數(shù)的處理。 博文目標(biāo):希望大家看了這篇博文后,對(duì)Mybatis整體運(yùn)行過(guò)程有一個(gè)清晰的認(rèn)識(shí)和把握。 1.什么是 MyBatis ? MyBatis 是一款優(yōu)秀的持久層框架,它支持定制化 SQL、存儲(chǔ)過(guò)程...

    mikasa 評(píng)論0 收藏0
  • Mybatis系列】從源碼角度深度理解Mybatis緩存特性

    摘要:一級(jí)緩存介紹及相關(guān)配置。在這個(gè)章節(jié),我們學(xué)習(xí)如何使用的一級(jí)緩存。一級(jí)緩存實(shí)驗(yàn)配置完畢后,通過(guò)實(shí)驗(yàn)的方式了解一級(jí)緩存的效果。源碼分析了解具體的工作流程后,我們隊(duì)查詢(xún)相關(guān)的核心類(lèi)和一級(jí)緩存的源碼進(jìn)行走讀。 我,后端Java工程師,現(xiàn)在美團(tuán)點(diǎn)評(píng)工作。愛(ài)健身,愛(ài)技術(shù),也喜歡寫(xiě)點(diǎn)文字。個(gè)人網(wǎng)站: http://kailuncen.me公眾號(hào): KailunTalk (凱倫說(shuō)) 前言 本文主要涉及...

    Ku_Andrew 評(píng)論0 收藏0
  • Mybatis系列】從源碼角度深度理解Mybatis緩存特性

    摘要:一級(jí)緩存介紹及相關(guān)配置。在這個(gè)章節(jié),我們學(xué)習(xí)如何使用的一級(jí)緩存。一級(jí)緩存實(shí)驗(yàn)配置完畢后,通過(guò)實(shí)驗(yàn)的方式了解一級(jí)緩存的效果。源碼分析了解具體的工作流程后,我們隊(duì)查詢(xún)相關(guān)的核心類(lèi)和一級(jí)緩存的源碼進(jìn)行走讀。 我,后端Java工程師,現(xiàn)在美團(tuán)點(diǎn)評(píng)工作。愛(ài)健身,愛(ài)技術(shù),也喜歡寫(xiě)點(diǎn)文字。個(gè)人網(wǎng)站: http://kailuncen.me公眾號(hào): KailunTalk (凱倫說(shuō)) 前言 本文主要涉及...

    young.li 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<