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