通过mybatis拦截器获取到执行的sql语句,如果我的service层报错,怎么才能让拦截器中的sql语句不保存下来

在使用 MyBatis 时,如果你想通过拦截器获取执行的 SQL 语句,并且在 service 层报错时不保存这些 SQL 语句,可以通过以下步骤实现:

  1. 创建 MyBatis 拦截器

    • 这个拦截器将拦截 MyBatis 执行的 SQL 语句,并将其保存到某个地方(例如内存中的一个列表)。
  2. 在拦截器中保存 SQL 语句

    • 使用 ThreadLocal 或其他类似机制来保存当前线程中的 SQL 语句。
  3. 在 service 层捕获异常

    • 在 service 层使用 try-catch 块捕获异常,并在 catch 块中清理保存的 SQL 语句。
  4. 清理保存的 SQL 语句

    • 当 service 层捕获到异常时,清理当前线程中的 SQL 语句,以确保这些语句不会被保存。

具体实现步骤

1. 创建 MyBatis 拦截器

首先,创建一个 MyBatis 拦截器来拦截 SQL 语句:

java
import org.apache.ibatis.executor.statement.StatementHandler; import org.apache.ibatis.plugin.*; import java.sql.Statement; import java.util.Properties; @Intercepts({ @Signature(type = StatementHandler.class, method = "query", args = {Statement.class, ResultSetHandler.class}), @Signature(type = StatementHandler.class, method = "update", args = {Statement.class}), @Signature(type = StatementHandler.class, method = "batch", args = {Statement.class}) }) public class SqlInterceptor implements Interceptor { private static final ThreadLocal<String> currentSql = new ThreadLocal<>(); @Override public Object intercept(Invocation invocation) throws Throwable { StatementHandler statementHandler = (StatementHandler) invocation.getTarget(); String sql = statementHandler.getBoundSql().getSql(); currentSql.set(sql); try { return invocation.proceed(); } finally { // Optionally clear the ThreadLocal here if not needed later } } @Override public Object plugin(Object target) { return Plugin.wrap(target, this); } @Override public void setProperties(Properties properties) { // No properties needed } public static String getCurrentSql() { return currentSql.get(); } public static void clearCurrentSql() { currentSql.remove(); } }

2. 配置 MyBatis 拦截器

在 MyBatis 配置文件中注册这个拦截器:

xml
<plugins> <plugin interceptor="com.example.SqlInterceptor"/> </plugins>

3. 在 service 层捕获异常

在 service 层捕获异常并处理保存的 SQL 语句:

java
import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service public class MyService { @Transactional public void myMethod() { try { // 执行数据库操作 // ... } catch (Exception e) { // 捕获异常并清理保存的 SQL 语句 SqlInterceptor.clearCurrentSql(); // 处理异常 throw e; } } }

4. 清理保存的 SQL 语句

确保在捕获到异常时清理当前线程中的 SQL 语句:

java
public class SqlInterceptorUtils { public static void clearSqlOnError() { SqlInterceptor.clearCurrentSql(); } }

在你的 catch 块中调用 SqlInterceptorUtils.clearSqlOnError()

总结

通过以上步骤,你可以在 MyBatis 拦截器中获取执行的 SQL 语句,并在 service 层报错时确保这些 SQL 语句不被保存下来。关键在于使用 ThreadLocal 来保存和清理当前线程中的 SQL 语句,并在 service 层捕获异常时清理这些 SQL 语句。