MyBatis StatementHandler 是如何与数据库进行交互的?

发布于:2025-03-23 ⋅ 阅读:(28) ⋅ 点赞:(0)

StatementHandler 在 MyBatis 中扮演着 连接 MyBatis 框架和 JDBC API 的桥梁 的角色。 它的核心作用是 处理 JDBC Statement 对象,并负责 MyBatis 与数据库的实际交互StatementHandler 封装了所有与 JDBC Statement 对象相关的操作,使得 MyBatis 的其他组件 (例如 Executor) 无需直接操作 JDBC API,而是通过 StatementHandler 提供的接口与数据库进行交互。

StatementHandler 与数据库交互的核心步骤和机制:

  1. StatementHandler 的创建:

    • StatementHandler 实例由 Executor 创建。 Executor 会根据 MappedStatement 对象中定义的 statementType 属性 (例如 STATEMENT, PREPARED, CALLABLE),创建不同类型的 StatementHandler 实现类实例 (例如 SimpleStatementHandler, PreparedStatementHandler, CallableStatementHandler)。
    • StatementHandler 的创建通常发生在 Executor.query()Executor.update() 等 SQL 执行方法内部,在真正执行 SQL 语句之前。
  2. StatementHandler.prepare() 方法:准备 JDBC Statement 对象

    • StatementHandlerprepare(Connection connection, Integer transactionTimeout) 方法负责 创建 JDBC Statement 对象
    • 根据 MappedStatementstatementType 属性,创建不同类型的 Statement 对象:
      • statementType="STATEMENT": 创建 java.sql.Statement 对象 (普通 Statement)。 适用于不需要预编译 SQL 或参数绑定的简单 SQL 语句。
      • statementType="PREPARED" (默认): 创建 java.sql.PreparedStatement 对象 (预编译 Statement)。 适用于大多数场景,可以提高性能和安全性,支持参数绑定。
      • statementType="CALLABLE": 创建 java.sql.CallableStatement 对象 (可调用 Statement)。 适用于调用数据库存储过程或函数。
    • 使用传入的 Connection 对象创建 Statement Connection 对象通常由 Transaction 对象提供,代表当前事务的数据库连接。
    • 设置 Statement 的超时时间 (transactionTimeout)。 如果 transactionTimeout 不为 null,会调用 statement.setQueryTimeout(transactionTimeout) 设置 Statement 的超时时间,防止 SQL 执行时间过长。
    • 返回创建好的 JDBC Statement 对象。
  3. StatementHandler.parameterize() 方法:设置 SQL 参数

    • StatementHandlerparameterize(Statement statement) 方法负责 为 JDBC Statement 对象设置 SQL 参数
    • 根据 MappedStatement 中定义的参数映射 (ParameterMapping),从传入的参数对象 (parameterObject) 中获取参数值。 参数映射信息包括参数的属性名、jdbcType、typeHandler 等。
    • 使用 TypeHandler 将 Java 参数值转换为 JDBC 类型的值,并通过 JDBC StatementsetXXX() 方法 (例如 PreparedStatement.setString(), PreparedStatement.setInt(), CallableStatement.registerOutParameter() 等) 将参数值设置到 Statement 对象中。
    • 不同类型的 StatementHandler 实现类,会采用不同的参数设置方式:
      • PreparedStatementHandler: 使用 PreparedStatement.setXXX() 方法设置参数 (最常用)。
      • CallableStatementHandler: 使用 CallableStatement.setXXX() 设置输入参数,使用 CallableStatement.registerOutParameter() 注册输出参数。
      • SimpleStatementHandler: 对于 Statement 对象,参数通常直接拼接在 SQL 语句中 (不安全,不推荐)。 在 MyBatis 中,SimpleStatementHandler 实际上并不直接处理参数设置 (参数设置通常交给 ParameterHandler 完成,ParameterHandler 再委托给 TypeHandler 进行类型转换和参数设置)。
  4. StatementHandler.query() 方法:执行 SQL 查询并处理 ResultSet

    • StatementHandlerquery(Statement statement, ResultHandler resultHandler) 方法负责 执行 SQL 查询语句,并处理查询结果集 (ResultSet)
    • 调用 JDBC Statement.execute()Statement.executeQuery() 方法执行 SQL 查询语句,获取 ResultSet 对象。 具体调用哪个方法取决于 MappedStatement 的 SQL 类型 (SELECT 调用 executeQuery(), 其他调用 execute())。
    • 使用 ResultHandler 对象逐行处理 ResultSet ResultHandler 负责遍历 ResultSet,并根据 ResultMapresultType 定义的映射规则,将每一行数据映射到 Java 对象。
    • 返回查询结果列表 (List)。 ResultHandler 会将映射后的 Java 对象添加到结果列表中,query() 方法最终返回这个结果列表。
    • 在处理 ResultSet 过程中,StatementHandler 会委托给 ResultSetHandler 组件进行更具体的结果集处理和映射操作。
  5. StatementHandler.update() 方法:执行 SQL 更新语句

    • StatementHandlerupdate(Statement statement) 方法负责 执行 SQL 更新语句 (INSERT, UPDATE, DELETE)。
    • 调用 JDBC Statement.execute()Statement.executeUpdate() 方法执行 SQL 更新语句。 具体调用哪个方法取决于 MappedStatement 的 SQL 类型 (INSERT, UPDATE, DELETE 通常调用 executeUpdate(), 某些特殊情况可能调用 execute()).
    • 返回受影响的行数 (int)。 update() 方法返回执行 SQL 更新语句后,数据库受影响的行数。
  6. StatementHandler.batch() 方法:执行批量 SQL 语句 (BatchExecutor 使用)

    • StatementHandlerbatch(Statement statement) 方法负责 执行批量 SQL 语句 (BatchExecutor 使用)
    • 将多条 SQL 语句添加到 JDBC Statement 对象的批处理队列中 (例如 PreparedStatement.addBatch()).
    • 在所有 SQL 语句添加到批处理队列后,调用 Statement.executeBatch() 方法一次性执行批处理队列中的所有 SQL 语句。
    • 返回一个 List<BatchResult>, 包含了每条 SQL 语句的执行结果 (受影响的行数或异常信息)。

StatementHandler 接口的主要方法:

  • StatementHandler(Executor executor, MappedStatement mappedStatement, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) (构造器): 创建 StatementHandler 实例。
  • Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException;: 准备 JDBC Statement 对象。
  • void parameterize(Statement statement) throws SQLException;: 为 JDBC Statement 对象设置 SQL 参数。
  • <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException;: 执行 SQL 查询语句,并处理结果集。
  • int update(Statement statement) throws SQLException;: 执行 SQL 更新语句 (INSERT, UPDATE, DELETE)。
  • void batch(Statement statement) throws SQLException;: 执行批量 SQL 语句 (BatchExecutor 使用)。

StatementHandler 的实现类:

MyBatis 提供了以下几种 StatementHandler 接口的实现类,对应不同的 JDBC Statement 类型:

  • SimpleStatementHandler: 处理 java.sql.Statement 对象 (普通 Statement)。 最简单的 StatementHandler 实现。
  • PreparedStatementHandler: 处理 java.sql.PreparedStatement 对象 (预编译 Statement)。 最常用的 StatementHandler 实现。
  • CallableStatementHandler: 处理 java.sql.CallableStatement 对象 (可调用 Statement)。 用于调用数据库存储过程或函数。
  • RoutingStatementHandler: 路由 StatementHandler。 根据 MappedStatementstatementType 属性,动态地选择使用 SimpleStatementHandler, PreparedStatementHandler, 或 CallableStatementHandler 中的一个。 RoutingStatementHandler 本身不直接处理 Statement,而是作为其他 StatementHandler 的路由和委托。

总结 StatementHandler 与数据库的交互:

  • StatementHandler 是 MyBatis 与数据库交互的桥梁,负责处理 JDBC Statement 对象。
  • StatementHandler 通过 prepare(), parameterize(), query(), update(), batch() 等方法,完成 JDBC Statement 对象的创建、参数设置、SQL 执行和结果处理等操作。
  • StatementHandler 内部使用 JDBC API (例如 Connection, Statement, ResultSet) 与数据库进行交互。
  • StatementHandler 抽象了底层的 JDBC 操作细节,为 MyBatis 的其他组件提供了更高层次的、更易于使用的 SQL 执行接口。
  • MyBatis 提供了多种 StatementHandler 实现类,对应不同的 JDBC Statement 类型,满足不同的 SQL 执行需求.

网站公告

今日签到

点亮在社区的每一天
去签到