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