MyBatis StatementHandler是如何创建 Statement 对象的? 如何执行 SQL 语句?

在MyBatis中,StatementHandler负责创建Statement对象并执行SQL语句。以下是其具体流程:
1. StatementHandler.prepare() 方法:创建 JDBC Statement 对象

StatementHandler.prepare(Connection connection, Integer transactionTimeout) 方法是核心方法,负责基于 MappedStatement 配置创建相应的 JDBC Statement 对象。

以下是 prepare() 方法内部发生步骤的分解:

  • 输入参数:

    • Connection connection:将用于创建 Statement 的 JDBC Connection 对象。此 Connection 通常由 MyBatis 的 Transaction 组件管理。
    • Integer transactionTimeout:一个可选的事务超时值(以秒为单位),用于 Statement
  • 确定 Statement 类型:
    StatementHandler 检查其持有的 MappedStatement 对象以确定 statementTypestatementType 在 Mapper XML 文件中通过 <select><insert><update><delete> 元素中的 statementType 属性进行配置。可能的取值包括:

    • STATEMENT:用于普通的 java.sql.Statement
    • PREPARED:用于 java.sql.PreparedStatement(默认且最常用)。
    • CALLABLE:用于 java.sql.CallableStatement(用于存储过程/函数)。
  • 创建 JDBC Statement 对象:
    基于确定的 statementTypeStatementHandler 使用提供的 Connection 对象来创建相应的 JDBC Statement 实例:

    • statementType="STATEMENT" (SimpleStatementHandler):

      Statement statement = connection.createStatement(); // 使用 Connection.createStatement()
      

      SimpleStatementHandler 使用 connection.createStatement() 创建一个普通的 Statement 对象。 这是最简单的类型,适用于没有参数的基本 SQL。

    • statementType="PREPARED" (PreparedStatementHandler - 默认):

      PreparedStatement statement =
### MyBatis 手动打印 SQL 语句的方法 在 MyBatis 中,可以通过多种方式手动打印 SQL 语句。以下是详细的实现方法: #### 1. 使用日志框架打印 MyBatis 支持多种日志框架(如 Log4j、SLF4J 等),通过配置日志级别为 `DEBUG` 或更低,可以自动打印生成的 SQL 语句[^5]。例如,在 `application.yml` 中设置如下内容: ```yaml logging: level: com.example.mapper: DEBUG ``` 这里的 `com.example.mapper` 是 Mapper 接口所在的包路径,请根据实际情况调整。 #### 2. 使用 MyBatis 的 `SqlSession` 打印 如果需要手动控制 SQL 的打印,可以在代码中通过 `SqlSession` 获取生成的 SQL 语句。以下是一个示例: ```java import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; public class SqlPrinter { public static void printSql(SqlSessionFactory sqlSessionFactory, String statementName, Object parameter) { SqlSession sqlSession = sqlSessionFactory.openSession(); try { org.apache.ibatis.mapping.MappedStatement ms = sqlSession.getConfiguration().getMappedStatement(statementName); org.apache.ibatis.scripting.defaults.DefaultSqlBuilder sqlBuilder = new org.apache.ibatis.scripting.defaults.DefaultSqlBuilder(ms.getSqlSource().getBoundSql(parameter).getSql()); System.out.println("Generated SQL: " + sqlBuilder.getSql()); } catch (Exception e) { e.printStackTrace(); } finally { sqlSession.close(); } } } ``` 上述代码通过 `sqlSessionFactory` 和 `statementName` 获取对应的 SQL 语句,并打印到控制台[^3]。 #### 3. 使用拦截器打印 MyBatis 提供了插件机制,可以通过自定义拦截器来打印 SQL 语句。以下是一个简单的拦截器实现: ```java import org.apache.ibatis.executor.statement.StatementHandler; import org.apache.ibatis.plugin.*; import java.sql.Connection; import java.util.Properties; @Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})}) public class SqlPrintInterceptor implements Interceptor { @Override public Object intercept(Invocation invocation) throws Throwable { StatementHandler statementHandler = (StatementHandler) invocation.getTarget(); String sql = statementHandler.getBoundSql().getSql(); System.out.println("Executing SQL: " + sql); return invocation.proceed(); } @Override public Object plugin(Object target) { return Plugin.wrap(target, this); } @Override public void setProperties(Properties properties) {} } ``` 将拦截器注册到 MyBatis 配置中即可生效[^5]。 #### 4. 使用工具类打印 MyBatis 提供了一个 `SqlRunner` 工具类,可以直接执行原生 SQL 并打印语句[^4]。以下是一个示例: ```java import org.apache.ibatis.jdbc.SqlRunner; public class SqlRunnerExample { public static void main(String[] args) { String sql = "SELECT * FROM users WHERE id = ?"; Object param = 1; List<Map<String, Object>> result = SqlRunner.run(sql, param).listMaps(); System.out.println("Executed SQL: " + sql); System.out.println("Result: " + result); } } ``` --- ### 注意事项 - 确保项目中没有禁用 SQL 日志的相关配置。 - 如果使用拦截器打印 SQL,请注意性能影响,建议仅在开发或调试环境中启用。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冰糖心书房

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值