国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Mybatis執(zhí)行器(Executor)

這篇具有很好參考價(jià)值的文章主要介紹了Mybatis執(zhí)行器(Executor)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

Executor簡(jiǎn)介

Executor

Executor是MyBatis的核心接口之一,其中定義了數(shù)據(jù)庫(kù)操作的基本方法。在實(shí)際應(yīng)用中經(jīng)常涉及的SqlSession接口的功能,都是基于Executor接口實(shí)現(xiàn)的。

BaseExecutor

BaseExecutor是一個(gè)實(shí)現(xiàn)了Executor接口的抽象類(lèi),它實(shí)現(xiàn)了Executor 接口的大部分方法。BaseExecutor 中主要提供了緩存管理和事務(wù)管理的基本功能。繼承BaseExecutor 的子類(lèi)只要實(shí)現(xiàn)四個(gè)基本方法來(lái)完成數(shù)據(jù)庫(kù)的相關(guān)操作即可,這四個(gè)方法是:doUpdate()方法、doQuery()方法、doQueryCursor()方法、doFlushstatement()方法, 其余的功能在BaseExecutor中實(shí)現(xiàn)。

SimpleExecutor

SimpleExecutor 繼承了BaseExecutor 抽象類(lèi),它是最簡(jiǎn)單的 Executor 接口實(shí)現(xiàn)。Executor使用了模板方法模式,一級(jí)緩存等固定不變的操作都封裝到了BaseExecutor中,SimpleExecutor中就不必再關(guān)心一級(jí)緩存等操作,只需要專(zhuān)注實(shí)現(xiàn)4個(gè)基本方法的實(shí)現(xiàn)即可。

ReuseExecutor

在傳統(tǒng)的JDBC編程中,重用Statement對(duì)象是常用的一種優(yōu)化手段,該優(yōu)化手段可以減少SQL預(yù)編譯的開(kāi)銷(xiāo)以及創(chuàng)建和銷(xiāo)毀 Statement 對(duì)象的開(kāi)銷(xiāo),從而提高性能。
ReuseExecutor提供了Statement重用的功能,ReuseExecutor 中通過(guò)statementMap字段(HashMap<String, Statement>類(lèi)型)緩存使用過(guò)的 Statement 對(duì)象,key是SQL 語(yǔ)句,value是SQL對(duì)應(yīng)的Statement對(duì)象。
ReuseExecutor.doQuery()、doQueryCursor()、doUpdate()方法的實(shí)現(xiàn)與SimpleExecutor 中對(duì)應(yīng)方法的實(shí)現(xiàn)一樣,區(qū)別在于其中調(diào)用的 prepareStatement()方法,SimpleExecutor 每次都會(huì)通過(guò)JDBC Connection創(chuàng)建新的Statement對(duì)象,而ReuseExecutor則會(huì)先嘗試重用StatementMap中緩存的Statement對(duì)象。

BatchExecutor

應(yīng)用系統(tǒng)在執(zhí)行一條SQL語(yǔ)句時(shí),會(huì)將SQL語(yǔ)句以及相關(guān)參數(shù)通過(guò)網(wǎng)絡(luò)發(fā)送到數(shù)據(jù)庫(kù)系統(tǒng)。對(duì)于頻繁操作數(shù)據(jù)庫(kù)的應(yīng)用系統(tǒng)來(lái)說(shuō),如果執(zhí)行一條SQL語(yǔ)句就向數(shù)據(jù)庫(kù)發(fā)送一次請(qǐng)求,很多時(shí)間會(huì)浪費(fèi)在網(wǎng)絡(luò)通信上。使用批量處理的優(yōu)化方式可以在客戶(hù)端緩存多條SQL語(yǔ)句,并在合適的時(shí)機(jī)將多條SQL語(yǔ)句打包發(fā)送給數(shù)據(jù)庫(kù)執(zhí)行,從而減少網(wǎng)絡(luò)方面的開(kāi)銷(xiāo),提升系統(tǒng)的性能。
不過(guò)有一點(diǎn)需要注意,在批量執(zhí)行多條SQL語(yǔ)句時(shí),每次向數(shù)據(jù)庫(kù)發(fā)送的SQL語(yǔ)句條數(shù)是有上限的,如果超過(guò)這個(gè)上限,數(shù)據(jù)庫(kù)會(huì)拒絕執(zhí)行這些SQL語(yǔ)句并拋出異常。所以批量發(fā)送SQL語(yǔ)句的時(shí)機(jī)很重要。

執(zhí)行器功能演示

代碼準(zhǔn)備

創(chuàng)建配置文件mybatis-config.xml
<?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>
        <property name="driver" value="com.mysql.cj.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&amp;characterEncoding=utf-8&amp;useSSL=false&amp;serverTimezone=Asia/Shanghai&amp;allowPublicKeyRetrieval=true" />
        <property name="username" value="root" />
        <property name="password" value="123456" />
    </properties>

    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>

    <environments default="default">
        <environment id="default">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}" />
                <property name="url" value="${url}" />
                <property name="username" value="${username}" />
                <property name="password" value="${password}" />
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="mapper/EmployeeMapper.xml" />
    </mappers>

</configuration>
創(chuàng)建實(shí)體類(lèi)EmployeeDO
@Data
@NoArgsConstructor
@AllArgsConstructor
public class EmployeeDO {

    private Integer id;

    private String name;

    private Integer age;

    private String phone;
}
創(chuàng)建EmployeeMapper接口
public interface EmployeeMapper {

    EmployeeDO getEmployeeById(Integer id);

    int addEmployee(EmployeeDO employeeDO);
}
創(chuàng)建EmployeeMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ys.mybatis.mapper.EmployeeMapper">

    <select id="getEmployeeById" resultType="com.ys.mybatis.DO.EmployeeDO">
        select * from employee where id = #{id}
    </select>

    <insert id="addEmployee" useGeneratedKeys="true" keyProperty="id">
       insert into employee(`name`, `age`, `phone`) VALUES (#{name},#{age},#{phone})
    </insert>

</mapper>
創(chuàng)建測(cè)試類(lèi)EmployeeTest
@Slf4j
public class EmployeeTest1 {

    private SqlSessionFactory sqlSessionFactory;

    private Configuration configuration;

    @BeforeEach
    public void before() {
        InputStream inputStream = ConfigurationTest.class.getClassLoader().getResourceAsStream("mybatis-config.xml");
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        configuration = sqlSessionFactory.getConfiguration();
    }

    @Test
    public void queryForSimpleExecutor() {
        SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.SIMPLE);
        EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
        EmployeeDO firstQuery = employeeMapper.getEmployeeById(1);
        EmployeeDO secondQuery = employeeMapper.getEmployeeById(2);
        System.out.println(firstQuery);
        System.out.println(secondQuery);
    }

    @Test
    public void queryForReuseExecutor() {
        SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.REUSE);
        EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
        EmployeeDO firstQuery = employeeMapper.getEmployeeById(1);
        EmployeeDO secondQuery = employeeMapper.getEmployeeById(2);
        System.out.println(firstQuery);
        System.out.println(secondQuery);
    }

    @Test
    public void batchProcessingForSimpleExecutor() {
        Random random = new Random();

        SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.SIMPLE);
        EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);

        long start = System.currentTimeMillis();

        for (int i = 0; i < 1000; i++) {
            EmployeeDO employee = new EmployeeDO(null, getRandomName(), random.nextInt(100), getRandomPhone());
            employeeMapper.addEmployee(employee);
        }

        sqlSession.commit();

        long end = System.currentTimeMillis();

        System.out.println("共耗時(shí):" + (end - start) / 1000);

    }

    @Test
    public void batchProcessingForReuseExecutor() {
        Random random = new Random();

        SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.REUSE);
        EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);

        long start = System.currentTimeMillis();

        for (int i = 0; i < 1000; i++) {
            EmployeeDO employee = new EmployeeDO(null, getRandomName(), random.nextInt(100), getRandomPhone());
            employeeMapper.addEmployee(employee);
        }

        sqlSession.commit();

        long end = System.currentTimeMillis();

        System.out.println("共耗時(shí):" + (end - start) / 1000);

    }


    @Test
    public void batchProcessingForBatchExecutor() {
        boolean autoCommit = false;
        Environment environment = configuration.getEnvironment();
        Transaction transaction = environment.getTransactionFactory().newTransaction(environment.getDataSource(), TransactionIsolationLevel.REPEATABLE_READ, autoCommit);
        BatchExecutor batchExecutor = new BatchExecutor(configuration, transaction);
        Random random = new Random();

        try (DefaultSqlSession sqlSession = new DefaultSqlSession(configuration, batchExecutor, autoCommit)) {
            EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);

            long start = System.currentTimeMillis();

            for (int i = 0; i < 1000; i++) {
                EmployeeDO employee = new EmployeeDO(null, getRandomName(), random.nextInt(100), getRandomPhone());
                employeeMapper.addEmployee(employee);
            }

            sqlSession.commit();

            long end = System.currentTimeMillis();

            System.out.println("共耗時(shí):" + (end - start) / 1000);
        }
    }


    private String getRandomName() {
        return UUID.randomUUID().toString().replaceAll("-", "").substring(0, 5);
    }

    private String getRandomPhone() {
        StringBuilder sb = new StringBuilder("1");
        Random random = new Random();
        IntStream.range(0, 10).forEach(i -> sb.append(random.nextInt(10)));
        return sb.toString();
    }

}

查詢(xún) : SimpleExecutor vs?ReuseExecutor

執(zhí)行queryForSimpleExecutor

executor 執(zhí)行器,mybatis,mybatis,java,后端

每執(zhí)行一次查詢(xún),預(yù)編譯一次

執(zhí)行queryForReuseExecutor

executor 執(zhí)行器,mybatis,mybatis,java,后端executor 執(zhí)行器,mybatis,mybatis,java,后端

多次查詢(xún),只預(yù)編譯一次

批量插入 : SimpleExecutor vs?ReuseExecutor vs?BatchExecutor

執(zhí)行batchProcessingForSimpleExecutor

executor 執(zhí)行器,mybatis,mybatis,java,后端

插入1000條數(shù)據(jù)耗時(shí) : 55s

執(zhí)行batchProcessingForReuseExecutor

executor 執(zhí)行器,mybatis,mybatis,java,后端

插入1000條數(shù)據(jù)耗時(shí) : 47s

執(zhí)行batchProcessingForBatchExecutor

executor 執(zhí)行器,mybatis,mybatis,java,后端

插入1000條數(shù)據(jù)耗時(shí) : 21s

原因簡(jiǎn)析
  • ReuseExecutor? vs SimpleExecutor : 減少了預(yù)編譯次數(shù)
  • BatchExecutor vs?ReuseExecutor? : 減少了與數(shù)據(jù)庫(kù)交互次數(shù)

PS :?ReuseExecutor和SimpleExecutor在執(zhí)行批量插入的時(shí)候其實(shí)性能差距不太大,要是執(zhí)行ReuseExecutor的批量插入時(shí)剛好機(jī)器負(fù)載大,執(zhí)行SimpleExecutor的批量插入時(shí)機(jī)器負(fù)載小,有可能出現(xiàn)SimpleExecutor的批量插入用時(shí)更少的情況

源碼簡(jiǎn)析

SimpleExecutor.doQuery() vs?ReuseExecutor.doQuery()

executor 執(zhí)行器,mybatis,mybatis,java,后端

executor 執(zhí)行器,mybatis,mybatis,java,后端

SimpleExecutor的doQuery()方法和ReuseExecutor的doQuery()方法基本上是一致的,主要差異就是prepareStatement這個(gè)方法的內(nèi)部實(shí)現(xiàn)。SimpleExecutor每次都重新編譯Statement,而ReuseExecutor則是將Statement緩存起來(lái),以供下次查詢(xún)使用

SimpleExecutor.doQuery() vs?BatchExecutor.doQuery()

executor 執(zhí)行器,mybatis,mybatis,java,后端

如果僅執(zhí)行查詢(xún)操作,SimpleExecutor的doQuery()方法和BatchExecutor的doQuery()方法的效果是一樣的,只是BatchExecutor的doQuery()方法會(huì)多一個(gè)批量刷新的方法。BatchExecutor執(zhí)行器執(zhí)行插入或者更新操作的時(shí)候不會(huì)立即執(zhí)行,而是封裝成BatchResult對(duì)象,等執(zhí)行flushStatements方法的時(shí)候才是真正執(zhí)行相關(guān)操作。即BatchExecutor在執(zhí)行更新操作中間執(zhí)行了查詢(xún)操作也會(huì)觸發(fā)批處理,如果更新操作中間沒(méi)有查詢(xún)操作,那只有等到執(zhí)行sqlSession的commit方法才會(huì)執(zhí)行flushStatements

BatchExecutor的更新操作

executor 執(zhí)行器,mybatis,mybatis,java,后端

BatchExecutor會(huì)拿本次執(zhí)行的sql和MappedStatement與上一次的對(duì)比,如果是一致的,則從緩存中獲取上一次使用的Statement,減少了預(yù)編譯次數(shù),這一點(diǎn)類(lèi)似ReuseExecutor的查詢(xún)。

PS : ReuseExecutor的doQuery是根據(jù)sql查找緩存,BatchExecutor的doUpdate是根據(jù)sql和MappedStatement查找緩存。個(gè)人理解:不同Statement的timeout和fetchSize可能不同,而更新操作是比較重要的,所以不能混用文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-852873.html

到了這里,關(guān)于Mybatis執(zhí)行器(Executor)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶(hù)投稿,該文觀(guān)點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Junit執(zhí)行器Runner探索之旅

    單元測(cè)試是每個(gè)程序員必備的技能,而Runner是每個(gè)單元測(cè)試類(lèi)必有屬性。本文通過(guò)解讀Junit源碼,介紹junit中每個(gè)執(zhí)行器的使用方法,讓讀者在單元測(cè)試時(shí),可以靈活的使用Runner執(zhí)行器。 在今年的敏捷團(tuán)隊(duì)建設(shè)中,京東物流通過(guò)Suite執(zhí)行器實(shí)現(xiàn)了一鍵自動(dòng)化單元測(cè)試。Juint除了

    2024年02月08日
    瀏覽(24)
  • PgSQL-執(zhí)行器機(jī)制-Unique算子

    PgSQL-執(zhí)行器機(jī)制-Unique算子

    PgSQL-執(zhí)行器機(jī)制-Unique算子 PgSQL中輸出去重的元組有多種方法,比如通過(guò)HashAgg或者GroupAgg。這里我們介紹第三種方法,通過(guò)Unique算子來(lái)完成這個(gè)功能。當(dāng)然語(yǔ)句上可以是:select distinct(id1) from t; 執(zhí)行器執(zhí)行算子的函數(shù)都是ExecXXX,其中XXX代表某個(gè)算子。Unique算子的執(zhí)行是由函數(shù)

    2024年02月07日
    瀏覽(17)
  • 機(jī)械臂速成小指南(五):末端執(zhí)行器

    機(jī)械臂速成小指南(五):末端執(zhí)行器

    ?????????需要機(jī)械臂相關(guān)資源的同學(xué)可以在評(píng)論區(qū)中留言哦?????? 指南目錄??: ????機(jī)械臂速成小指南(零點(diǎn)五):機(jī)械臂相關(guān)資源???? 機(jī)械臂速成小指南(零):指南主要內(nèi)容及分析方法 機(jī)械臂速成小指南(一):機(jī)械臂發(fā)展概況 機(jī)械臂速成小指南(二):

    2024年02月03日
    瀏覽(23)
  • 【PostgreSQL內(nèi)核學(xué)習(xí)(二十三)—— 執(zhí)行器(ExecEndPlan)】

    【PostgreSQL內(nèi)核學(xué)習(xí)(二十三)—— 執(zhí)行器(ExecEndPlan)】

    聲明 :本文的部分內(nèi)容參考了他人的文章。在編寫(xiě)過(guò)程中,我們尊重他人的知識(shí)產(chǎn)權(quán)和學(xué)術(shù)成果,力求遵循合理使用原則,并在適用的情況下注明引用來(lái)源。 本文主要參考了 postgresql-10.1 的開(kāi)源代碼和《OpenGauss數(shù)據(jù)庫(kù)源碼解析》和《PostgresSQL數(shù)據(jù)庫(kù)內(nèi)核分析》一書(shū) ??在這三

    2024年01月17日
    瀏覽(30)
  • 【PostgreSQL內(nèi)核學(xué)習(xí)(二十一)—— 執(zhí)行器(InitPlan)】

    【PostgreSQL內(nèi)核學(xué)習(xí)(二十一)—— 執(zhí)行器(InitPlan)】

    聲明 :本文的部分內(nèi)容參考了他人的文章。在編寫(xiě)過(guò)程中,我們尊重他人的知識(shí)產(chǎn)權(quán)和學(xué)術(shù)成果,力求遵循合理使用原則,并在適用的情況下注明引用來(lái)源。 本文主要參考了 postgresql-10.1 的開(kāi)源代碼和《OpenGauss數(shù)據(jù)庫(kù)源碼解析》和《PostgresSQL數(shù)據(jù)庫(kù)內(nèi)核分析》一書(shū) ??在【

    2024年01月16日
    瀏覽(24)
  • Camunda 7.x 系列【53】Job 執(zhí)行器

    有道無(wú)術(shù),術(shù)尚可求,有術(shù)無(wú)道,止于術(shù)。 本系列Spring Boot 版本 2.7.9 本系列Camunda 版本 7.19.0 源碼地址:https://gitee.com/pearl-organization/camunda-study-demo Job Executor 即任務(wù)執(zhí)行器,是 Camunda 中的一個(gè)調(diào)度組件,負(fù)責(zé)執(zhí)行異步后臺(tái)作業(yè)。 Job 表示 Job Executor 執(zhí)行的某一作業(yè),例如,在定

    2024年02月09日
    瀏覽(33)
  • xxl-job執(zhí)行器無(wú)法自動(dòng)注冊(cè)

    xxl-job執(zhí)行器無(wú)法自動(dòng)注冊(cè)

    問(wèn)題描述 在springboot項(xiàng)目里配置了xxl-job2.3.0,但是執(zhí)行器無(wú)法自動(dòng)注冊(cè) yaml配置如下: 執(zhí)行器無(wú)法自動(dòng)注冊(cè)到xxl-job-admin 排查過(guò)程 經(jīng)過(guò)debug發(fā)現(xiàn),是spring沒(méi)有加載xxlJobExecutor這個(gè)Bean debug流程(SpringApplication.run()–SpringApplication.refreshContext()–SpringApplication.refresh() --SpringApplication

    2024年02月16日
    瀏覽(22)
  • Spring Boot 中的任務(wù)執(zhí)行器是什么,如何使用

    Spring Boot 中的任務(wù)執(zhí)行器是什么,如何使用

    Spring Boot 是一個(gè)非常流行的 Java 開(kāi)發(fā)框架,它的核心理念是通過(guò)簡(jiǎn)單的配置和約定來(lái)提高開(kāi)發(fā)效率。在很多情況下,我們需要在后臺(tái)執(zhí)行一些任務(wù),比如異步處理、定時(shí)任務(wù)等等。為了簡(jiǎn)化這些任務(wù)的開(kāi)發(fā)和管理,Spring Boot 提供了一個(gè)任務(wù)執(zhí)行器(Task Executor)。 任務(wù)執(zhí)行器

    2024年02月15日
    瀏覽(19)
  • 【源碼分析】XXL-JOB的執(zhí)行器的注冊(cè)流程

    目的:分析xxl-job執(zhí)行器的注冊(cè)過(guò)程 流程: 獲取執(zhí)行器中所有被注解( @xxlJjob )修飾的 handler 執(zhí)行器注冊(cè)過(guò)程 執(zhí)行器中任務(wù)執(zhí)行過(guò)程 版本: xxl-job 2.3.1 建議:下載 xxl-job 源碼,按流程圖 debug 調(diào)試, 看堆棧信息并按文章內(nèi)容理解執(zhí)行流程 。 完整流程圖: 部分流程圖: 首先啟

    2023年04月22日
    瀏覽(23)
  • 【微軟】【ICLR 2022】TAPEX:通過(guò)學(xué)習(xí)神經(jīng) SQL 執(zhí)行器進(jìn)行表預(yù)訓(xùn)練

    【微軟】【ICLR 2022】TAPEX:通過(guò)學(xué)習(xí)神經(jīng) SQL 執(zhí)行器進(jìn)行表預(yù)訓(xùn)練

    重磅推薦專(zhuān)欄: 《大模型AIGC》;《課程大綱》 本專(zhuān)欄致力于探索和討論當(dāng)今最前沿的技術(shù)趨勢(shì)和應(yīng)用領(lǐng)域,包括但不限于ChatGPT和Stable Diffusion等。我們將深入研究大型模型的開(kāi)發(fā)和應(yīng)用,以及與之相關(guān)的人工智能生成內(nèi)容(AIGC)技術(shù)。通過(guò)深入的技術(shù)解析和實(shí)踐經(jīng)驗(yàn)分享,

    2024年02月05日
    瀏覽(27)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包