通过mybatis拦截器获取到执行的sql语句,如果我的service层报错,怎么才能让拦截器中的sql语句不保存下来
在使用 MyBatis 时,如果你想通过拦截器获取执行的 SQL 语句,并且在 service 层报错时不保存这些 SQL 语句,可以通过以下步骤实现:
创建 MyBatis 拦截器:
- 这个拦截器将拦截 MyBatis 执行的 SQL 语句,并将其保存到某个地方(例如内存中的一个列表)。
在拦截器中保存 SQL 语句:
- 使用 ThreadLocal 或其他类似机制来保存当前线程中的 SQL 语句。
在 service 层捕获异常:
- 在 service 层使用 try-catch 块捕获异常,并在 catch 块中清理保存的 SQL 语句。
清理保存的 SQL 语句:
- 当 service 层捕获到异常时,清理当前线程中的 SQL 语句,以确保这些语句不会被保存。
具体实现步骤
1. 创建 MyBatis 拦截器
首先,创建一个 MyBatis 拦截器来拦截 SQL 语句:
javaimport 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 语句:
javaimport 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 语句:
javapublic class SqlInterceptorUtils {
public static void clearSqlOnError() {
SqlInterceptor.clearCurrentSql();
}
}
在你的 catch
块中调用 SqlInterceptorUtils.clearSqlOnError()
。
总结
通过以上步骤,你可以在 MyBatis 拦截器中获取执行的 SQL 语句,并在 service 层报错时确保这些 SQL 语句不被保存下来。关键在于使用 ThreadLocal
来保存和清理当前线程中的 SQL 语句,并在 service 层捕获异常时清理这些 SQL 语句。