SpringBoot MybatisPlus 打印SQL及参数
import java.text.DateFormat;
import lombok.extern.slf4j.Slf4j;
import cn.hutool.core.collection.CollUtil;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Properties;
import java.util.regex.Matcher;
import java.sql.Connection;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
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.reflection.DefaultReflectorFactory;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.type.TypeHandlerRegistry;
@Slf4j
@Component
@ConditionalOnProperty(prefix = "mybatis-plus", name = "customer-log", havingValue = "true")
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
public class SqlLogConf implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
StatementHandler handler = (StatementHandler) invocation.getTarget();
MetaObject object = MetaObject.forObject(handler,
SystemMetaObject.DEFAULT_OBJECT_FACTORY,
SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY,
new DefaultReflectorFactory());
MappedStatement statement = (MappedStatement) object.getValue("delegate.mappedStatement");
log.info("SQL执行类: {}", statement.getId());
log.info("SQL执行类型: {}", statement.getSqlCommandType().toString());
BoundSql bound = handler.getBoundSql();
Configuration configuration = statement.getConfiguration();
String sql = getFullSql(configuration, bound);
log.info("SQL: {}", sql);
long start = System.currentTimeMillis();
Object value = invocation.proceed();
long end = System.currentTimeMillis();
log.info("SQL耗时: {}ms", (end - start));
return value;
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
}
public String getFullSql(Configuration conf, BoundSql bound) {
Object object = bound.getParameterObject();
List<ParameterMapping> list = bound.getParameterMappings();
String sql = bound.getSql().replaceAll("[\\s]+", " ").toLowerCase(Locale.ROOT);
if (CollUtil.isNotEmpty(list) && object != null) {
TypeHandlerRegistry type = conf.getTypeHandlerRegistry();
if (type.hasTypeHandler(object.getClass())) {
sql = sql.replaceFirst("\\?", Matcher.quoteReplacement(getParaValue(object)));
} else {
MetaObject meta = conf.newMetaObject(object);
for (ParameterMapping parameterMapping : list) {
String name = parameterMapping.getProperty();
if (meta.hasGetter(name)) {
Object obj = meta.getValue(name);
sql = sql.replaceFirst("\\?", Matcher.quoteReplacement(getParaValue(obj)));
} else if (bound.hasAdditionalParameter(name)) {
Object obj = bound.getAdditionalParameter(name);
sql = sql.replaceFirst("\\?", Matcher.quoteReplacement(getParaValue(obj)));
} else {
sql = sql.replaceFirst("\\?", "缺失");
}
}
}
}
return sql;
}
private String getParaValue(Object obj) {
if (obj instanceof String) {
return "'" + obj + "'";
} else if (obj instanceof Date) {
DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.CHINA);
return "'" + formatter.format(new Date()) + "'";
} else {
if (obj != null) {
return obj.toString();
} else {
return "";
}
}
}
}