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