🚀 作者主页: 有来技术
🔥 开源项目: youlai-mall 🍃 vue3-element-admin 🍃 youlai-boot
🌺 仓库主页: Gitee 💫 Github 💫 GitCode
💖 欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请纠正!
目录
- 前言
- Executor 的作用与分类
- Executor 的源码解析
- SimpleExecutor
- ReuseExecutor
- BatchExecutor
- CachingExecutor 的作用
- 结语
- 开源项目
前言
MyBatis 作为一个强大的持久层框架,其灵活的映射机制和高效的数据库操作在Java开发中得到了广泛应用。其中,MyBatis 的四大核心组件之一 Executor,负责执行SQL语句、管理缓存以及处理查询结果。在本文中,将深度解析 MyBatis Executor 的内部工作原理,并对其一个关键实现组件——CachingExecutor 进行简要介绍。
Executor 的作用与分类
Executor是MyBatis的核心组件之一,主要负责以下职责:
-
执行 SQL 语句: Executor将用户传入的SQL语句交由StatementHandler处理,并执行最终的SQL操作。
-
缓存管理: 管理MyBatis的一级缓存(本地缓存)和二级缓存(全局缓存)。
-
结果集映射: 将数据库返回的结果集映射为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 {@Overridepublic 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<>();@Overridepublic 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 {@Overridepublic 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 通过缓存机制在一级缓存和二级缓存中提高查询性能。其工作原理涉及一级缓存和二级缓存的处理:
- 一级缓存处理: 在执行查询操作时,``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;
}
- 二级缓存处理: 在执行更新操作时,
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 微服务商城
Github | Gitee | |
---|---|---|
后端 | youlai-mall 🍃 | youlai-mall 🍃 |
前端 | mall-admin🌺 | mall-admin 🌺 |
移动端 | mall-app 🍌 | mall-app 🍌 |
- SpringBoot 3+ Vue3 单体权限管理系统
Github | Gitee | |
---|---|---|
后端 | youlai-boot 🍃 | youlai-boot 🍃 |
前端 | vue3-element-admin 🌺 | vue3-element-admin 🌺 |