
Mybatis输出完整Sql - Interceptor ...
@Intercepts(
{
@Signature(type = Executor.class, method = "query"
, args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
@Signature(type = Executor.class, method = "query"
, args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class
, CacheKey.class, BoundSql.class}),
@Signature(type = Executor.class, method = "update"
, args = {MappedStatement.class, Object.class}),
}
)
@Slf4j
public class MybatisSqlLogInterceptor implements Interceptor {
private static final String LONG_PARAM_DESC = ".....";
@Setter
Supplier<Long> slowSqlThreshold = () -> 1000L;
@Setter
Supplier<Long> paramLengthLogLimit = () -> 1024L;
@Override
public Object intercept(Invocation invocation) throws Throwable {
Object proceed;
try {
long start = System.currentTimeMillis();
proceed = invocation.proceed();
long costTime = System.currentTimeMillis() - start;
if (costTime > slowSqlThreshold.get()) {
SqlDetail sqlDetail = getSqlDetail(invocation);
log.info("executeSql: {} pararm:[{}] methodName:[{}] rowsNum:[{}] elapsedTime:{}ms"
, sqlDetail.getSql()
, sqlDetail.getParam()
, sqlDetail.getMethodName()
, getReturnRows(proceed)
, costTime);
}
} catch (Exception exception) {
SqlDetail sqlDetail = getSqlDetail(invocation);
log.error("executeSql: {} pararm:[{}] methodName:[{}] "
, sqlDetail.getSql()
, sqlDetail.getParam()
, sqlDetail.getMethodName()
, exception);
throw exception;
}
return proceed;
}
@Nullable
private SqlDetail getSqlDetail(Invocation invocation) {
SqlDetail sqlDetail = new SqlDetail();
MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
if (null != mappedStatement) {
String methodLocate = mappedStatement.getId();
sqlDetail.setMethodName(getMethodName(methodLocate, '.'));
}
Object parameter = null;
if (invocation.getArgs().length > 1) {
parameter = invocation.getArgs()[1];
}
BoundSql boundSql = mappedStatement.getBoundSql(parameter);
sqlDetail.setSql(boundSql.getSql());
Configuration configuration = mappedStatement.getConfiguration();
Object parameterObject = boundSql.getParameterObject();
StringBuffer sqlParam = new StringBuffer(128);
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
if (parameterObject != null) {
TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
String param = ConvertUtil.toString(parameterObject);
sqlParam.append(param.length() > paramLengthLogLimit.get()
? param.substring(0, paramLengthLogLimit.get().intValue()) + LONG_PARAM_DESC : param);
sqlDetail.setParam(sqlParam.toString());
} else {
MetaObject metaObject = configuration.newMetaObject(parameterObject);
for (ParameterMapping parameterMapping : parameterMappings) {
String propertyName = parameterMapping.getProperty();
if (metaObject.hasGetter(propertyName)) {
String param = ConvertUtil.toString(metaObject.getValue(propertyName));
sqlParam.append(param.length() > paramLengthLogLimit.get()
? param.substring(0, paramLengthLogLimit.get().intValue()) + LONG_PARAM_DESC
: param)
.append(',');
}
if (boundSql.hasAdditionalParameter(propertyName)) {
String param = ConvertUtil.toString(boundSql.getAdditionalParameter(propertyName));
sqlParam.append(param.length() > paramLengthLogLimit.get() ?
param.substring(0, paramLengthLogLimit.get().intValue()) + LONG_PARAM_DESC
: param)
.append(',');
}
}
}
if (sqlParam.length() > 0) {
sqlDetail.setParam(sqlParam.deleteCharAt(sqlParam.length() - 1).toString());
}
}
return sqlDetail;
}
private Integer getReturnRows(Object proceed) {
if (proceed instanceof Collection) {
return ((Collection<?>) proceed).size();
}
if (proceed instanceof Map) {
return ((Map) proceed).size();
}
if (proceed instanceof Integer) {
return (Integer) proceed;
}
return 0;
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
}
String getMethodName(String str, char separator) {
if (str == null || str.length() == 0) {
return str;
}
final int pos = str.lastIndexOf(separator);
if (pos == -1) {
return str;
}
final int secondPos = str.lastIndexOf(separator, pos - 1);
if (secondPos == -1) {
return str;
}
return str.substring(secondPos + 1);
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public static class SqlDetail {
private String sql;
private String param;
private String methodName;
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南