MyBatis 四大核心组件之 Executor 源码解析

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: MyBatis 四大核心组件之 Executor 源码解析

1.png

前言


MyBatis 作为一个强大的持久层框架,其灵活的映射机制和高效的数据库操作在Java开发中得到了广泛应用。其中,MyBatis 的四大核心组件之一 Executor,负责执行SQL语句、管理缓存以及处理查询结果。在本文中,将深度解析 MyBatis Executor 的内部工作原理,并对其一个关键实现组件——CachingExecutor 进行简要介绍。


Executor 的作用与分类

2.pngExecutor是MyBatis的核心组件之一,主要负责以下职责:


1.执行 SQL 语句: Executor将用户传入的SQL语句交由StatementHandler处理,并执行最终的SQL操作。


2.缓存管理: 管理MyBatis的一级缓存(本地缓存)和二级缓存(全局缓存)。


3.结果集映射: 将数据库返回的结果集映射为Java对象。


根据具体实现方式,Executor分为三种主要类型:


SimpleExecutor: 每执行一次update或select,就开启一个Statement对象,用完立即关闭。


ReuseExecutor: 执行update或select,以SQL语句作为key查找Statement对象,存在就使用,不存在就创建,用完不关闭Statement对象,而是放置于Map内,供下一次使用。


BatchExecutor: 批量执行Statement,没有二级缓存功能。


Executor 的源码解析


SimpleExecutor


SimpleExecutor是MyBatis默认的Executor实现,其关键源码如下:

public class SimpleExecutor extends BaseExecutor {
    @Override
    public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
        Statement stmt = null;
        try {
            Configuration configuration = ms.getConfiguration();
            StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);
            stmt = prepareStatement(handler, ms.getStatementLog());
            return handler.update(stmt);
        } finally {
            closeStatement(stmt);
        }
    }
    @Override
    @SuppressWarnings("unchecked")
    public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
        Statement stmt = null;
        try {
            Configuration configuration = ms.getConfiguration();
            StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
            stmt = prepareStatement(handler, ms.getStatementLog());
            return handler.<E>query(stmt, resultHandler);
        } finally {
            closeStatement(stmt);
        }
    }
    // ... 其他方法 ...
}

ReuseExecutor


ReuseExecutor在执行update或select时,通过SQL语句作为key缓存Statement对象,下次执行相同的SQL语句时直接从缓存中获取:

public class ReuseExecutor extends BaseExecutor {
    private final Map<String, Statement> statementMap = new HashMap<>();
    @Override
    public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
        Statement stmt = null;
        try {
            Configuration configuration = ms.getConfiguration();
            StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);
            stmt = prepareStatement(handler, ms.getStatementLog());
            return handler.update(stmt);
        } finally {
            closeStatement(stmt);
        }
    }
    @Override
    @SuppressWarnings("unchecked")
    public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
        Statement stmt = statementMap.get(ms.getKey());
        try {
            if (stmt == null) {
                Configuration configuration = ms.getConfiguration();
                StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
                stmt = prepareStatement(handler, ms.getStatementLog());
                List<E> result = handler.<E>query(stmt, resultHandler);
                statementMap.put(ms.getKey(), stmt);
                return result;
            } else {
                return handleQueryResult(ms, parameter, rowBounds, resultHandler, stmt);
            }
        } finally {
            // ...
        }
    }
    // ... 其他方法 ...
}

BatchExecutor


BatchExecutor 专门用于批量执行 Statement,没有二级缓存功能。适用于需要一次性执行多个 SQL 语句的场景。

public class BatchExecutor extends BaseExecutor {
    @Override
    public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
        // 执行更新操作
        return delegate.update(ms, parameter);
    }
    @Override
    @SuppressWarnings("unchecked")
    public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
        // 执行查询操作
        return delegate.<E>query(ms, parameter, rowBounds, resultHandler, ms.getKey(), boundSql);
    }
    // ... 其他方法 ...
}

CachingExecutor 的作用


CachingExecutor 通过缓存机制在一级缓存和二级缓存中提高查询性能。其工作原理涉及一级缓存和二级缓存的处理:


1.一级缓存处理: 在执行查询操作时,``CachingExecutor 首先通过 delegate 执行SQL语句,然后将查询结果存储到一级缓存中,以提高后续相同查询的性能。

public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
    // 从缓存中获取结果
    List<E> list = delegate.query(ms, parameter, rowBounds, resultHandler, key, boundSql);
    // 将结果添加到缓存
    tcm.putObject(key, list);
    return list;
}

2.二级缓存处理: 在执行更新操作时,CachingExecutor 会清空一级缓存,然后通过 delegate 执行实际的更新操作。在事务提交时,将一级缓存中的数据写入二级缓存中,以便多个 SqlSession 共享相同的数据。

public int update(MappedStatement ms, Object parameter) throws SQLException {
    // 清空一级缓存
    flushCacheIfRequired(ms);
    // 执行更新操作
    int count = delegate.update(ms, parameter);
    // 提交事务时,将缓存数据写入二级缓存
    tcm.commit();
    return count;
}

结语


本文深入解析 MyBatis 四大核心组件之一的 Executor,着重介绍 SimpleExecutor、ReuseExecutor、BatchExecuto r的源码实现,同时补充CacheExecutor的作用与示例。通过源码解析和示例,全面理解MyBatis持久层框架的关键组件。


开源项目


  • SpringCloud + Vue3 微服务商城


SpringBoot 3+ Vue3 单体权限管理系统

相关文章
|
11天前
|
存储 安全 Java
深度长文解析SpringWebFlux响应式框架15个核心组件源码
以上是Spring WebFlux 框架核心组件的全部介绍了,希望可以帮助你全面深入的理解 WebFlux的原理,关注【威哥爱编程】,主页里可查看V哥每天更新的原创技术内容,让我们一起成长。
|
12天前
|
关系型数据库 分布式数据库 数据库
PolarDB-X源码解析:揭秘分布式事务处理
【7月更文挑战第3天】**PolarDB-X源码解析:揭秘分布式事务处理** PolarDB-X,应对大规模分布式事务挑战,基于2PC协议确保ACID特性。通过预提交和提交阶段保证原子性与一致性,使用一致性快照隔离和乐观锁减少冲突,结合故障恢复机制确保高可用。源码中的事务管理逻辑展现了优化的分布式事务处理流程,为开发者提供了洞察分布式数据库核心技术的窗口。随着开源社区的发展,更多创新实践将促进数据库技术进步。
18 3
|
12天前
|
前端开发 开发者
深入解析Vite.js源码
【7月更文挑战第1天】Vite.js 深入解析:以其无bundle开发、动态ES模块加载提升开发效率;本地HTTP服务器配合WebSocket实现热更新;按需加载减少资源占用;预构建优化生产环境性能;基于Rollup的插件系统增强灵活性。Vite,一个创新且高效的前端构建工具。
20 0
|
17天前
|
前端开发 程序员 UED
全面解析layui:掌握基础知识与实用技能(1. 核心组件与模块 2. 布局与容器 3. 弹出层与提示框;1. 数据表格与数据表单 2. 表单验证与提交 3. 图片轮播与导航菜单)
全面解析layui:掌握基础知识与实用技能(1. 核心组件与模块 2. 布局与容器 3. 弹出层与提示框;1. 数据表格与数据表单 2. 表单验证与提交 3. 图片轮播与导航菜单)
23 0
|
2月前
|
SQL Java 数据库连接
挺详细的spring+springmvc+mybatis配置整合|含源代码
挺详细的spring+springmvc+mybatis配置整合|含源代码
|
2月前
|
算法 Java 数据库连接
Spring+MySQL+数据结构+集合,Alibaba珍藏版mybatis手写文档
Spring+MySQL+数据结构+集合,Alibaba珍藏版mybatis手写文档
|
2月前
|
Java 数据库连接 Spring
Spring 整合mybatis
Spring 整合mybatis
30 2
|
25天前
|
Java 数据库连接 mybatis
在Spring Boot应用中集成MyBatis与MyBatis-Plus
在Spring Boot应用中集成MyBatis与MyBatis-Plus
59 5
|
25天前
|
Java 数据库连接 数据库
实现Spring Boot与MyBatis结合进行数据库历史数据的定时迁移
实现Spring Boot与MyBatis结合进行数据库历史数据的定时迁移
37 2
|
27天前
|
缓存 NoSQL Java
在 SSM 架构(Spring + SpringMVC + MyBatis)中,可以通过 Spring 的注解式缓存来实现 Redis 缓存功能
【6月更文挑战第18天】在SSM(Spring+SpringMVC+MyBatis)中集成Redis缓存,涉及以下步骤:添加Spring Boot的`spring-boot-starter-data-redis`依赖;配置Redis连接池(如JedisPoolConfig)和连接工厂;在Service层使用`@Cacheable`注解标记缓存方法,指定缓存名和键生成策略;最后,在主配置类启用缓存注解。通过这些步骤,可以利用Spring的注解实现Redis缓存。
51 2

推荐镜像

更多