MyBatis 源码解析:BatchExecutor 与 SimpleExecutor 详解
MyBatis 是一个持久层框架,它简化了数据库操作的复杂性。MyBatis 通过将 SQL 语句与 Java 对象绑定,使得数据访问变得更加灵活和简洁。在 MyBatis 的核心中,Executor
是一个非常重要的接口,它负责执行 SQL 语句并处理数据库操作。
在 MyBatis 中,Executor
有多种实现,其中 SimpleExecutor
和 BatchExecutor
是最常用的两种。本文将详细解析这两种 Executor
的工作原理、代码实现和使用场景,并通过具体示例来说明它们的区别和应用场景。
目录
MyBatis 的 Executor 介绍
在 MyBatis 中,Executor
是负责执行 SQL 语句的核心组件。MyBatis 提供了不同的 Executor
实现,以满足不同的使用需求。Executor
的主要任务包括:
- 执行 SQL 语句
- 处理事务
- 缓存 SQL 执行结果
Executor
接口包含以下主要方法:
update(String statement, Object parameter)
:执行更新操作query(String statement, Object parameter, RowBounds rowBounds)
:执行查询操作commit(boolean required)
:提交事务rollback(boolean required)
:回滚事务
MyBatis 默认使用 SimpleExecutor
,但在某些场景下,BatchExecutor
可能更为合适。
SimpleExecutor 详解
SimpleExecutor 的实现
SimpleExecutor
是 MyBatis 提供的最简单的 Executor
实现,它直接执行每个 SQL 语句而不进行批量操作。以下是 SimpleExecutor
的主要实现代码:
javaCopy Codepublic class SimpleExecutor implements Executor {
private final Transaction transaction;
public SimpleExecutor(Transaction transaction) {
this.transaction = transaction;
}
@Override
public int update(String statement, Object parameter) throws SQLException {
try (Statement stmt = transaction.getConnection().createStatement()) {
return stmt.executeUpdate(statement);
}
}
@Override
public <E> List<E> query(String statement, Object parameter, RowBounds rowBounds) throws SQLException {
try (Statement stmt = transaction.getConnection().createStatement()) {
ResultSet rs = stmt.executeQuery(statement);
// Process the ResultSet and return the results
return processResultSet(rs);
}
}
// Other methods omitted for brevity
}
在 SimpleExecutor
中,每次执行 SQL 时都会创建一个新的 Statement
对象,并直接执行 SQL 语句。它不支持批量处理,也不会缓存 SQL 执行结果。
使用场景
SimpleExecutor
适用于以下场景:
- SQL 语句较少,不需要批量执行
- 对性能要求不高,直接执行 SQL 即可
- 需要支持事务,但不需要批量处理
示例代码
以下是使用 SimpleExecutor
执行 SQL 语句的示例代码:
javaCopy CodeTransaction transaction = new JdbcTransaction(connection);
Executor executor = new SimpleExecutor(transaction);
String sql = "INSERT INTO users (name, age) VALUES ('Alice', 30)";
executor.update(sql, null);
String query = "SELECT * FROM users";
List<User> users = executor.query(query, null, RowBounds.DEFAULT);
BatchExecutor 详解
BatchExecutor 的实现
BatchExecutor
是 MyBatis 提供的另一种 Executor
实现,它支持批量处理 SQL 语句。以下是 BatchExecutor
的主要实现代码:
javaCopy Codepublic class BatchExecutor implements Executor {
private final Transaction transaction;
private final List<String> batchStatements = new ArrayList<>();
public BatchExecutor(Transaction transaction) {
this.transaction = transaction;
}
@Override
public int update(String statement, Object parameter) throws SQLException {
batchStatements.add(statement);
return 0; // No immediate execution
}
@Override
public <E> List<E> query(String statement, Object parameter, RowBounds rowBounds) throws SQLException {
// BatchExecutor doesn't support query operations
throw new UnsupportedOperationException("BatchExecutor does not support query operations");
}
public void flushStatements() throws SQLException {
try (Statement stmt = transaction.getConnection().createStatement()) {
for (String statement : batchStatements) {
stmt.addBatch(statement);
}
stmt.executeBatch();
}
batchStatements.clear();
}
// Other methods omitted for brevity
}
在 BatchExecutor
中,SQL 语句不会立即执行,而是被存储在一个批量语句列表中。调用 flushStatements()
方法时,所有存储的 SQL 语句会被一起执行,这样可以提高执行效率。
使用场景
BatchExecutor
适用于以下场景:
- 需要执行大量相似的 SQL 语句,如批量插入或更新
- 对性能有较高要求,需要减少数据库交互次数
- 事务处理需要保证批量操作的一致性
示例代码
以下是使用 BatchExecutor
执行批量 SQL 语句的示例代码:
javaCopy CodeTransaction transaction = new JdbcTransaction(connection);
BatchExecutor executor = new BatchExecutor(transaction);
String sql1 = "INSERT INTO users (name, age) VALUES ('Bob', 25)";
String sql2 = "INSERT INTO users (name, age) VALUES ('Charlie', 35)";
executor.update(sql1, null);
executor.update(sql2, null);
executor.flushStatements(); // Execute all batched statements
SimpleExecutor 与 BatchExecutor 的比较
性能
SimpleExecutor
每次执行 SQL 语句时都创建一个新的Statement
对象,并立即执行 SQL,因此在执行大量 SQL 语句时性能较差。BatchExecutor
将多个 SQL 语句存储在批量语句列表中,一次性执行,减少了与数据库的交互次数,因此在执行批量操作时性能更优。
使用场景
SimpleExecutor
更适用于对性能要求不高的场景,或者 SQL 语句较少的情况。BatchExecutor
更适用于需要执行大量 SQL 语句的场景,如批量插入、更新或删除操作,尤其是在对性能有较高要求的情况下。
事务处理
SimpleExecutor
在每次执行 SQL 语句时都会参与事务处理,事务提交或回滚时,只有当前的 SQL 语句会受到影响。BatchExecutor
在执行flushStatements()
时,所有的 SQL 语句会一起提交或回滚,保证了批量操作的一致性。
总结
SimpleExecutor
和 BatchExecutor
是 MyBatis 中两个重要的 Executor
实现。SimpleExecutor
适用于简单的 SQL 执行场景,而 BatchExecutor
则适用于批量处理操作。在实际应用中,可以根据具体的业务需求选择合适的 Executor
实现,以达到最佳的性能和效果。通过理解这两种 Executor
的工作原理和使用场景,可以更好地利用 MyBatis 提供的功能,优化数据库操作的性能。