打印个SQL还不老实

摘要

  1. Mybatis开启sql打印,还不把参数给拼接到sql语句中,给本地开发带来极大不方便
  2. Mybatis-Plus是通过收集日志完成sql语句与参数结合,有些IDEA对这个插件还支持的不好
  3. 不如自己搞个小工具,只要是本地方式启动的,将在控制台输出所有的查询和更新sql语句,并监听sql执行时间

小工具来了

  1. 注入
@Configuration
public class MybatisConfig {
    @Bean
    @Conditional(LocalStartCondition.class)
    public SqlCheckInterceptor performanceInterceptor() {
        return new SqlCheckInterceptor();
    }
}
  1. 注入条件
public class LocalStartCondition implements Condition {
    @Override
    public boolean matches(ConditionContext conditionContext, @Nullable AnnotatedTypeMetadata annotatedTypeMetadata) {
        return "local".equals(conditionContext.getEnvironment().getActiveProfiles()[0]);
    }
}
  1. 拦截器
@Intercepts({
        @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
        @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),
})
public class SqlCheckInterceptor implements Interceptor {

    private static final Log logger = LogFactory.getLog(SqlCheckInterceptor.class);
    private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
        Object parameterObject = null;
        if (invocation.getArgs().length > 1) {
            parameterObject = invocation.getArgs()[1];
        }
        long start = SystemClock.now();
        Object result = invocation.proceed();
        long timing = SystemClock.now() - start;
        String statementId = mappedStatement.getId();
        BoundSql boundSql = mappedStatement.getBoundSql(parameterObject);
        Configuration configuration = mappedStatement.getConfiguration();
        String sql = getSql(boundSql, parameterObject, configuration);
        if (logger.isInfoEnabled()) {
            String formatSqlStr = StringPool.NEWLINE +
                    "SQL-in-method===>:" + statementId + StringPool.NEWLINE +
                    "Execute-time====>:" + timing + " ms" + StringPool.NEWLINE +
                    "SQL-script===>:" + StringPool.NEWLINE +
                    sql + StringPool.NEWLINE;
            logger.info(formatSqlStr);
        }
        return result;
    }

    @Override
    public Object plugin(Object target) {
        if (target instanceof Executor) {
            return Plugin.wrap(target, this);
        }
        return target;
    }

    @Override
    public void setProperties(Properties properties) {
    }

    private String getSql(BoundSql boundSql, Object parameterObject, Configuration configuration) {
        String sql = boundSql.getSql().replaceAll("[\\s]+", " ");
        List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
        TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
        if (parameterMappings != null) {
            for (ParameterMapping parameterMapping : parameterMappings) {
                if (parameterMapping.getMode() != ParameterMode.OUT) {
                    Object value;
                    String propertyName = parameterMapping.getProperty();
                    if (boundSql.hasAdditionalParameter(propertyName)) {
                        value = boundSql.getAdditionalParameter(propertyName);
                    } else if (parameterObject == null) {
                        value = null;
                    } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
                        value = parameterObject;
                    } else {
                        MetaObject metaObject = configuration.newMetaObject(parameterObject);
                        value = metaObject.getValue(propertyName);
                    }
                    sql = replacePlaceholder(sql, value);
                }
            }
        }
        return sql;
    }

    private String replacePlaceholder(String sql, Object propertyValue) {
        String result;
        if (propertyValue != null) {
            if (propertyValue instanceof String) {
                result = "'" + propertyValue + "'";
            } else if (propertyValue instanceof Date) {
                result = "'" + DATE_FORMAT.format(propertyValue) + "'";
            } else {
                result = propertyValue.toString();
            }
        } else {
            result = "null";
        }
        return sql.replaceFirst("\\?", Matcher.quoteReplacement(result));
    }
}

废话

**粘贴代码的同时想想实现原理,对提升魂力有帮助。**

模范青蛙
65 声望15 粉丝

大道无情,唯变化永恒