打印个SQL还不老实
摘要
- Mybatis开启sql打印,还不把参数给拼接到sql语句中,给本地开发带来极大不方便
- Mybatis-Plus是通过收集日志完成sql语句与参数结合,有些IDEA对这个插件还支持的不好
- 不如自己搞个小工具,只要是本地方式启动的,将在控制台输出所有的查询和更新sql语句,并监听sql执行时间
小工具来了
- 注入
@Configuration
public class MybatisConfig {
@Bean
@Conditional(LocalStartCondition.class)
public SqlCheckInterceptor performanceInterceptor() {
return new SqlCheckInterceptor();
}
}
- 注入条件
public class LocalStartCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, @Nullable AnnotatedTypeMetadata annotatedTypeMetadata) {
return "local".equals(conditionContext.getEnvironment().getActiveProfiles()[0]);
}
}
- 拦截器
@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));
}
}
废话
**粘贴代码的同时想想实现原理,对提升魂力有帮助。**
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。