package com.dy.common.mybatis;
|
|
import java.lang.reflect.InvocationTargetException;
|
import java.util.Properties;
|
|
import lombok.extern.slf4j.Slf4j;
|
import org.apache.ibatis.executor.Executor;
|
import org.apache.ibatis.mapping.BoundSql;
|
import org.apache.ibatis.mapping.MappedStatement;
|
import org.apache.ibatis.plugin.Interceptor;
|
import org.apache.ibatis.plugin.Intercepts;
|
import org.apache.ibatis.plugin.Invocation;
|
import org.apache.ibatis.plugin.Plugin;
|
import org.apache.ibatis.plugin.Signature;
|
import org.apache.ibatis.session.Configuration;
|
import org.apache.ibatis.session.ResultHandler;
|
import org.apache.ibatis.session.RowBounds;
|
|
/**
|
* 拦截执行SQL发生异常的场景,并将执行错误,执行SQL和参数打印出来
|
* 拦截Executor里面的query和update方法
|
*/
|
@Intercepts({
|
@Signature(
|
method = "query",
|
type = Executor.class,
|
args = {
|
MappedStatement.class,
|
Object.class,
|
RowBounds.class,
|
ResultHandler.class
|
}
|
),
|
@Signature(
|
type = Executor.class,
|
method = "update",
|
args = {
|
MappedStatement.class,
|
Object.class
|
}
|
)
|
})
|
@Slf4j
|
public class PrintExceptionSqlInterceptor implements Interceptor {
|
|
@Override
|
public Object intercept(Invocation invocation) throws Throwable {
|
// 获取执行方法的MappedStatement参数
|
Object[] args = invocation.getArgs();
|
if(args != null && args.length > 1){
|
MappedStatement mappedStatement = (MappedStatement) args[0];
|
Object parameter = args[1];
|
|
String sqlId = mappedStatement.getId();
|
BoundSql boundSql = mappedStatement.getBoundSql(parameter);
|
Configuration configuration = mappedStatement.getConfiguration();
|
Object response;
|
try {
|
response = invocation.proceed();
|
} catch (Exception e) {
|
// 输出SQL异常信息
|
log.error("SQL ErrorException:", e);
|
log.error("SQL Id: {}", sqlId);
|
log.error("SQL Parameters: {}", boundSql.getParameterObject());
|
log.error("SQL: {}", PrintSqlHelp.getFullSql(configuration, boundSql));
|
// 根据源异常类型进行返回
|
if (e instanceof InvocationTargetException) {
|
throw new InvocationTargetException(e);
|
} else if (e instanceof IllegalAccessException) {
|
throw new IllegalAccessException(e.getMessage());
|
} else {
|
throw new RuntimeException(e);
|
}
|
}
|
return response;
|
}else{
|
return invocation.proceed();
|
}
|
}
|
|
/**
|
* 通过该方法决定要返回的对象是目标对象还是对应的代理
|
* 不要想的太复杂,一般就两种情况:
|
* <p>
|
* 1. return target; 直接返回目标对象,相当于当前Interceptor没起作用,不会调用上面的intercept()方法
|
* 2. return Plugin.wrap(target, this); 返回代理对象,会调用上面的intercept()方法
|
*
|
* @param target 目标对象
|
* @return 目标对象或者代理对象
|
*/
|
@Override
|
public Object plugin(Object target) {
|
return Plugin.wrap(target, this);
|
}
|
|
/**
|
* 用于获取在Configuration初始化当前的Interceptor时时候设置的一些参数
|
*
|
* @param properties Properties参数
|
*/
|
@Override
|
public void setProperties(Properties properties) {
|
}
|
|
|
}
|