问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

Executor Executors ExecutorService的区别与联系 在什么场景下运用,请详谈

发布网友 发布时间:2022-05-02 16:27

我来回答

2个回答

懂视网 时间:2022-05-02 20:48

Executor是Mybatis的一个核心接口,每一个SqlSession对象都会拥有一个Executor(执行器对象);这个执行对象负责[增删改查]的具体操作,我们可以简单的将它理解为JDBC中Statement的封装版。它的代码如下:

public interface Executor {
 ResultHandler NO_RESULT_HANDLER = null;
 int update(MappedStatement ms, Object parameter) throws SQLException;
 <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey cacheKey, BoundSql boundSql) throws SQLException;
 <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException;
 <E> Cursor<E> queryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds) throws SQLException;
 List<BatchResult> flushStatements() throws SQLException;
 void commit(boolean required) throws SQLException;
 void rollback(boolean required) throws SQLException;
 CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql);
 boolean isCached(MappedStatement ms, CacheKey key);
 void clearLocalCache();
 void deferLoad(MappedStatement ms, MetaObject resultObject, String property, CacheKey key, Class<?> targetType);
 Transaction getTransaction();
 void close(boolean forceRollback);
 boolean isClosed();
 void setExecutorWrapper(Executor executor);
}

Executor的继承结构

Executor的类图如下所示:

技术分享图片

Executor是一个接口,主要有两个实现类:分别是BaseExecutor和CachingExecutor。

BaseExecutor类

BaseExecutor是一个抽象类,这种通过抽象类实现接口的方式是适配器设计模式的体现,主要用于方便次一级子类对接口中方法的实现。BaseExecutor主要有三个实现类SimpleExecutor、ReuseExecutor和BatchExecutor。三个实现类分别对应executor对Statement对象管理方案。

  • 简单方案:一个Statement接口对象只执行一次,执行完毕就会Statement接口对象进行销毁。对应SimpleExecutor,被称为简单执行器,是MyBatis中默认使用的执行器,每执行一次update或select,就开启一个Statement对象,用完立刻关闭Statement对象(可以是Statement或PrepareStatement对象)。
  • 可重用方案:对应ReuseExecutor,被称为可重用执行器,重用指的是重复使用Statement,它会在内部利用一个Map把初始化的Statement都缓存起来,每次在执行一条SQL语句时,它都会去判断之前是否存在基于该SQL缓存的Statement对象,存在而且之前缓存的Statement对象对应的Connection还没有关闭的时候就继续用之前的Statement对象,否则将初始化一个新的Statement对象,并将其缓存起来。因为每一个新的SqlSession都有一个新的Executor对象,所以我们缓存在ReuseExecutor上的Statement的作用域是同一个SqlSession。
  • 批量处理方案:对应BatchExecutor,称为批处理执行器,用于将多个Statement对应的SQL语句,交给一个Statement对象一次输送到数据库,进行批处理操作。
  • CachingExecutor类

    CachingExecutor称为缓存执行器,MyBatis框架默认情况下使用执行器缓存执行器,可以提高查询效率,先从缓存中获取查询结果,存在就返回,不存在,再委托给Executor delegate去数据库取,delegate可以是SimpleExecutor、ReuseExecutor、BatchExecutor中任意一个。

    Executor对象初始化

    Executor的初始化是在SqlSessionFactory调用openSession方法期间初始化的,首先看一下SqlSessionFactory中的方法,具体代码如下:

    public interface SqlSessionFactory {
    
     SqlSession openSession();
    
     SqlSession openSession(boolean autoCommit);
     SqlSession openSession(Connection connection);
     SqlSession openSession(TransactionIsolationLevel level);
    
     SqlSession openSession(ExecutorType execType);
     SqlSession openSession(ExecutorType execType, boolean autoCommit);
     SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level);
     SqlSession openSession(ExecutorType execType, Connection connection);
    
     Configuration getConfiguration();
    
    }

    由代码可见,SqlSessionFactory中的openSession方法分为两类:带ExecutorType和不带ExecutorType的,此外每个类型还有四种,这里采用了重载的方法,方法名称相同,参数列表不同。下面进入到SqlSessionFactory的实现类DefaultSqlSessionFactory中查看openSession()d的实现,代码如下:

     @Override
     public SqlSession openSession(ExecutorType execType) {
     return openSessionFromDataSource(execType, null, false);
     }
    
     @Override
     public SqlSession openSession(TransactionIsolationLevel level) {
     return openSessionFromDataSource(configuration.getDefaultExecutorType(), level, false);
     }
    ...

    通过查看代码发现,所有的openSession方法都会走向openSessionFromDataSource方法中,openSessionFromDataSource的代码如下:

    private SqlSession openSessionFromConnection(ExecutorType execType, Connection connection) {
     try {
     boolean autoCommit;
     try {
     autoCommit = connection.getAutoCommit();
     } catch (SQLException e) {
     autoCommit = true;
     } 
     final Environment environment = configuration.getEnvironment();
     final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
     final Transaction tx = transactionFactory.newTransaction(connection);
     final Executor executor = configuration.newExecutor(tx, execType);
     return new DefaultSqlSession(configuration, executor, autoCommit);
     } catch (Exception e) {
     throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);
     } finally {
     ErrorContext.instance().reset();
     }
     }

    主要看其中的两行代码:

     final Executor executor = configuration.newExecutor(tx, execType);
     return new DefaultSqlSession(configuration, executor, autoCommit);

    这两行代码先产生executor,再产生了DefaultSqlSession对象,也验证了前面所说的执行器的初始化是在SqlSession初始化之前进行的。下面我们继续查看执行器的初始化过程,它的初始化是由Configuration完成的,初始化Executor的方法newExecutor()的代码如下所示:

    public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
     executorType = executorType == null ? defaultExecutorType : executorType;
     executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
     Executor executor;
     if (ExecutorType.BATCH == executorType) {
     executor = new BatchExecutor(this, transaction);
     } else if (ExecutorType.REUSE == executorType) {
     executor = new ReuseExecutor(this, transaction);
     } else {
     executor = new SimpleExecutor(this, transaction);
     }
     if (cacheEnabled) {
     executor = new CachingExecutor(executor);
     }
     executor = (Executor) interceptorChain.pluginAll(executor);
     return executor;
    }
    protected ExecutorType defaultExecutorType = ExecutorType.SIMPLE;

    由代码可见:首先判断初始化ExecutorType是否为空,若不为空,则默认执行器为SimpleExecutor。而这里的ExecutorType类型则是由openSession方法传入的,因而SqlSessionFactory中没有ExecutorType参数的openSession()则默认为SimpleExecutor。此外关注以下代码:

    protected boolean cacheEnabled = true;
    
    if (cacheEnabled) {
     executor = new CachingExecutor(executor);
    }

    这里是初始化CachingExecutor执行器,可见默认情况下CachingExecutor执行器是开启的。

    ExecutorType的选择

    ExecutorType是枚举类型,其代码如下:

    public enum ExecutorType {
     SIMPLE, REUSE, BATCH
    }

    ExecutorType的枚举值分别对应三种执行器类型:简单执行器、可重用执行器、批量执行器。

    ExecutorType的类型选择,有两种方式对其进行赋值。

    <settings>标签设置

    通过<settings>标签来设置当前工程中所有SqlSession对象使用的默认Executour。

    技术分享图片

    openSession方法指定

    通过SqlSessoinFactory中openSession方法来指定具体的SqlSession使用的执行器。

    技术分享图片

    SqlSession对象之Executor

    标签:方案   lca   set   cte   chain   增删改   rest   creat   参数   

    热心网友 时间:2022-05-02 17:56

    线程池的架构图如下:

    1. Executor

    它是"执行者"接口,它是来执行任务的。准确的说,Executor提供了execute()接口来执行已提交的 Runnable 任务的对象。Executor存在的目的是提供一种将"任务提交"与"任务如何运行"分离开来的机制。它只包含一个函数接口。


    2. Executors

    Executors是个静态工厂类。它通过静态工厂方法返回ExecutorService、ScheledExecutorService、ThreadFactory 和 Callable 等类的对象。


    3. ExecutorService

    ExecutorService继承于Executor。它是"执行者服务"接口,它是为"执行者接口Executor"服务而存在的;准确的话,ExecutorService提供了"将任务提交给执行者的接口(submit方法)","让执行者执行任务(invokeAll, invokeAny方法)"的接口等等。

    声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
    我在网上买了票,到取票的时候,我把订单号不小心删了?请问我该怎么... 在网上订了高铁票,不记得订单号,如何进行交费操作 用自己省份证在网上买的票,订单号搞忘了可以取到票吗? 珠宝设计画立体图的基本功是什么珠宝设计画立体图的基本功是什么呢_百... 你在太原吃过哪些特色面食? 林兰友生平仕途 太原哪家的面食好吃?有什么特色呢? 太原的哪些面食店十分有本地特色? 太原的面食有哪些 太原值得打卡的面食店有哪些? 在iphone上没能激活id怎么办 河北大厂现在收房交契税百分之多少 河北首套房和二套房的契税各是多少? 河北二手房契税怎么样收取 河北廊坊买房契税怎么算 2020年新房河北省石家庄第三套房契税是多少144平米以上? 河北邯郸房产契税如何征收 石家庄买房需要交什么税费? 宁波反诈中心电话打过来什么意思 宁波便民服务中心 宁波社保查询电话 81890服务中心可以咨询调动事项吗? 宁波818090服务中心电话改成什么了 有人安装过哈勃投资的股票软件吗 全球“芯片荒”!从“买不到”到“买不起”,芯片界发生了什么? 充yy币是充YY帐号还是通行证帐号呢? 为什么橙子吃起来是甜的榨出来果汁是酸的? 高庆海 是说评书的名家吗?郭德纲的师傅 刘功杰先生《三侠五义》还说吗?? 介绍一下过去或者现在比较好的相声节目。 农行掌上银行自助还款什么意思 手机视频剪辑怎么弄 手机上可免费剪辑视频吗?怎么弄 中文简体全拼输入法--输入法 中文简体全拼输入法 如何删除中文(简体)全拼输入法 QQ帐号不能登录,存在风险,怎样解除限制啊??? 没有工作单位,个人可以缴纳住房公积金吗 没在单位上班可以交公积金吗 “能在linux上使用的编程语言”是什么意思? 卡西欧冰韧系列5600怎么调日历 根据传入代码类型和SUUM代码没有找到对应FWCODE信息请检查osi_suum_code表配置 笔记本L490如何加装固态硬盘? thinkpad L490怎么样?跟T、S、E系列比,处在哪个位置? thinkpadL490机械硬盘排线是多少针? 图中这固态硬盘啥牌子的? tninkpad l490 能装内存条吗? 家用 游戏主机的配置? 求5000左右配置的电脑报表 电脑2014最新版微博背景音乐如何删除