MyBatis 源码解析:BatchExecutor 与 SimpleExecutor 详解

MyBatis 是一个持久层框架,它简化了数据库操作的复杂性。MyBatis 通过将 SQL 语句与 Java 对象绑定,使得数据访问变得更加灵活和简洁。在 MyBatis 的核心中,Executor 是一个非常重要的接口,它负责执行 SQL 语句并处理数据库操作。

在 MyBatis 中,Executor 有多种实现,其中 SimpleExecutorBatchExecutor 是最常用的两种。本文将详细解析这两种 Executor 的工作原理、代码实现和使用场景,并通过具体示例来说明它们的区别和应用场景。

目录

  1. MyBatis 的 Executor 介绍
  2. SimpleExecutor 详解
  3. BatchExecutor 详解
  4. SimpleExecutor 与 BatchExecutor 的比较
  5. 总结

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 Code
public 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 Code
Transaction 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 Code
public 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 Code
Transaction 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 语句会一起提交或回滚,保证了批量操作的一致性。

总结

SimpleExecutorBatchExecutor 是 MyBatis 中两个重要的 Executor 实现。SimpleExecutor 适用于简单的 SQL 执行场景,而 BatchExecutor 则适用于批量处理操作。在实际应用中,可以根据具体的业务需求选择合适的 Executor 实现,以达到最佳的性能和效果。通过理解这两种 Executor 的工作原理和使用场景,可以更好地利用 MyBatis 提供的功能,优化数据库操作的性能。