| New file | 
|  |  |  | 
|---|
|  |  |  | 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) { | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  | } | 
|---|