pms-parent/pms-common/src/main/java/com/dy/common/mybatis/MyBatisConfig.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
pms-parent/pms-common/src/main/java/com/dy/common/mybatis/PrintSqlHelp.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
pms-parent/pms-common/src/main/java/com/dy/common/mybatis/PrintSqlInterceptor.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
pms-parent/pms-common/src/main/java/com/dy/common/mybatis/MyBatisConfig.java
@@ -4,27 +4,70 @@ import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; import jakarta.annotation.PostConstruct; import org.apache.ibatis.session.SqlSessionFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @org.springframework.context.annotation.Configuration import java.util.List; @Configuration public class MyBatisConfig { @Autowired private List<SqlSessionFactory> sqlSessionFactoryList; @Value("${mybatis-plus.configuration.print-sql}") private boolean printSql; /** * 两个拦截器,自动生成ID,异常时输出SQL */ @PostConstruct public void addMyInterceptor() { for (SqlSessionFactory sqlSessionFactory : sqlSessionFactoryList) { org.apache.ibatis.session.Configuration conf = sqlSessionFactory.getConfiguration(); conf.addInterceptor(new AutoGenerateIdInterceptor()); conf.addInterceptor(new PrintExceptionSqlInterceptor()); if (printSql) { conf.addInterceptor(new PrintSqlInterceptor()); } } } /** * mybatisPlus的分面插件 * @return 拦截器 */ @Bean public PaginationInnerInterceptor paginationInnerInterceptor(){ return new PaginationInnerInterceptor() ; } /* @Value("${mybatis-plus.configuration.print-sql}") private boolean printSql; @Bean public ConfigurationCustomizer mybatisConfigurationCustomizer() { return configuration -> { configuration.addInterceptor(new AutoGenerateIdInterceptor()); configuration.addInterceptor(new PrintExceptionSqlInterceptor()); }; /* return new ConfigurationCustomizer() { @Override public void customize(MybatisConfiguration configuration) { configuration.addInterceptor(new AutoGenerateIdInterceptor()); configuration.addInterceptor(new PrintExceptionSqlInterceptor()); if (printSql) { configuration.addInterceptor(new PrintSqlInterceptor()); } }; */ //return new ConfigurationCustomizer() { // @Override // public void customize(MybatisConfiguration configuration) { // configuration.addInterceptor(new AutoGenerateIdInterceptor()); // configuration.addInterceptor(new PrintExceptionSqlInterceptor()); // } //}; } @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); @@ -32,5 +75,5 @@ // 如果有多数据源可以不配具体类型, 否则都建议配上具体的 DbType return interceptor; } */ } pms-parent/pms-common/src/main/java/com/dy/common/mybatis/PrintSqlHelp.java
New file @@ -0,0 +1,123 @@ package com.dy.common.mybatis; import org.apache.ibatis.mapping.BoundSql; import org.apache.ibatis.mapping.ParameterMapping; import org.apache.ibatis.reflection.MetaObject; import org.apache.ibatis.session.Configuration; import org.apache.ibatis.type.TypeHandlerRegistry; import java.text.DateFormat; import java.util.Date; import java.util.List; import java.util.Locale; /** * @Author: liurunyu * @Date: 2025/5/20 15:31 * @Description */ public class PrintSqlHelp { /** * 获取完整的执行SQL */ public static String getFullSql(Configuration configuration, BoundSql boundSql) { try { return parseAndExtractFullSql(configuration, boundSql); } catch (Exception e) { // 如果解析失败返回原始SQL return boundSql.getSql(); } } /** * 组装完整的sql语句并把对应的参数都代入到sql语句里面 * * @param configuration Configuration * @param boundSql BoundSql * @return sql完整语句 */ private static String parseAndExtractFullSql(Configuration configuration, BoundSql boundSql) { // 获取mapper里面方法上的参数 Object sqlParameter = boundSql.getParameterObject(); // sql语句里面需要的参数 List<ParameterMapping> parameterMappings = boundSql.getParameterMappings(); // sql原始语句(?还没有替换成我们具体的参数) String sql = boundSql.getSql().replaceAll("[\\s]+", " "); if (!parameterMappings.isEmpty() && sqlParameter != null) { // sql语句里面的?替换成真实的参数 TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry(); if (typeHandlerRegistry.hasTypeHandler(sqlParameter.getClass())) { sql = sql.replaceFirst("\\?", getParameterValue(sqlParameter)); } else { MetaObject metaObject = configuration.newMetaObject(sqlParameter); for (ParameterMapping parameterMapping : parameterMappings) { // 按顺序把?替换成对应的值 String propertyName = parameterMapping.getProperty(); if (metaObject.hasGetter(propertyName)) { Object obj = metaObject.getValue(propertyName); sql = sql.replaceFirst("\\?", getParameterValue(obj)); } else if (boundSql.hasAdditionalParameter(propertyName)) { Object obj = boundSql.getAdditionalParameter(propertyName); sql = sql.replaceFirst("\\?", getParameterValue(obj)); } } } } return sql; } /** * 获取参数对应的string值 * * @param obj 参数对应的值 * @return string */ private static String getParameterValue(Object obj) { String value; if (obj instanceof String) { value = "'" + obj + "'"; } else if (obj instanceof Date) { DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.CHINA); value = "'" + formatter.format(obj) + "'"; } else { if (obj != null) { value = obj.toString(); } else { value = ""; } } // 对特殊字符进行转义,方便之后处理替换 return value != null ? makeQueryStringAllRegExp(value) : ""; } /** * 转义正则特殊字符 ($()*+.[]?\^{} * \\需要第一个替换,否则replace方法替换时会有逻辑bug */ private static String makeQueryStringAllRegExp(String str) { if (str != null && !"".equals(str)) { return str.replace("\\", "\\\\") .replace("*", "\\*") .replace("+", "\\+") .replace("|", "\\|") .replace("{", "\\{") .replace("}", "\\}") .replace("(", "\\(") .replace(")", "\\)") .replace("^", "\\^") .replace("$", "\\$") .replace("[", "\\[") .replace("]", "\\]") .replace("?", "\\?") .replace(",", "\\,") .replace(".", "\\.") .replace("&", "\\&"); } return str; } } pms-parent/pms-common/src/main/java/com/dy/common/mybatis/PrintSqlInterceptor.java
New file @@ -0,0 +1,63 @@ package com.dy.common.mybatis; 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.Signature; import org.apache.ibatis.session.Configuration; import org.apache.ibatis.session.ResultHandler; import org.apache.ibatis.session.RowBounds; /** * @Author: liurunyu * @Date: 2025/5/20 15:31 * @Description */ /** * 拦截执行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 PrintSqlInterceptor implements Interceptor { @Override public Object intercept(Invocation invocation) throws Throwable { 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(); log.info("\nSQL Id: " + sqlId + "\nSQL Parameters: " + boundSql.getParameterObject() + "\nSQL: " + PrintSqlHelp.getFullSql(configuration, boundSql) + "\n"); } return invocation.proceed(); } }