MybatisPlus打印完整SQL不带问号
MybatisPlus 是一个优秀的 ORM 框架,提供了一些与 Mybatis 的基本功能相同的增强特性,常常被用在企业级应用中。
在 Mybatis 中,我们可以通过配置参数来开启 SQL 打印,但打印出来的 SQL 中含有问号占位符,不便于我们查看具体的 SQL 语句。
MybatisPlus 默认采用了和 Mybatis 相同的 SQL 打印功能,并输出的 SQL 带有问号,如果我们想要查看完整的 SQL 语句,而不是带有问号的占位符,可以通过以下方法进行配置。
方法一:使用日志输出完整的 SQL 语句
在 application.yml 或 application.properties 中配置以下参数:
logging:
level:
com.baomidou.mybatisplus.mapper: debug
这里的配置意味着启用了 MybatisPlus 的 SQL 打印,并将打印级别设置为 debug。MybatisPlus 会在控制台输出完整的 SQL 语句,不带有问号占位符。
但是,这种方法会导致控制台输出大量的 debug 日志,可能会影响系统的性能。所以,我们可以使用第二种方法。
方法二:使用自定义的 SQL 格式化插件
在 MybatisPlus 中,我们可以通过自定义 SQL 格式化插件来实现我们的目标。以下是具体的实现过程:
-
首先,我们需要实现一个 SQL 格式化器,将带有问号的 SQL 语句转化为不带问号的字符串:
```java
import com.baomidou.mybatisplus.core.toolkit.sql.SqlUtils;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;
import org.apache.ibatis.mapping.BoundSql;/*
* 自定义的 {@link org.apache.ibatis.mapping.ParameterHandler},
* 用于打印完整的 SQL 语句,不带有问号占位符
/
public class CompleteSqlSqlFormatInterceptor extends SqlFormatInterceptor {private static final Log logger = LogFactory.getLog(CompleteSqlSqlFormatInterceptor.class); @Override public Object doIntercept(Invocation invocation) throws Throwable { Object[] args = invocation.getArgs(); BoundSql boundSql = (BoundSql) args[1]; if (logger.isDebugEnabled()) { String sql = boundSql.getSql(); Object parameterObject = args[0]; String formatSql = SqlUtils.formatSql(sql, parameterObject); logger.debug(" SQL:\n" + formatSql); } return super.doIntercept(invocation); }
}
```
需要注意的是,我们继承了 MybatisPlus 提供的
SqlFormatInterceptor
类,并重写了其doIntercept
方法。在这个方法中,我们先拿到 BoundSql 参数,然后将其中的 SQL 和参数整合到一起,调用SqlUtils.formatSql
方法来解析 SQL ,返回不带问号占位符的字符串。最后,通过 logger 输出到日志中。 -
然后,我们需要将自定义的插件注册到 MybatisPlus 中:
```java
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.core.enums.SqlLike;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.parser.ISqlParser;
import com.baomidou.mybatisplus.core.parser.SqlParserHelper;
import com.baomidou.mybatisplus.core.toolkit.GlobalConfigUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import org.apache.ibatis.builder.MapperBuilderAssistant;
import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator;
import org.apache.ibatis.executor.keygen.KeyGenerator;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;
import org.apache.ibatis.mapping.;
import org.apache.ibatis.plugin.;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.apache.ibatis.scripting.LanguageDriver;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeHandler;import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;/*
* MybatisPlus 自定义的 SQL 格式化插件
/
@Intercepts(@Signature(
type = StatementHandler.class,
method = "prepare",
args = {Connection.class, Integer.class})
)
public class CompleteSqlSqlFormatPlugin implements Interceptor {private static final Log logger = LogFactory.getLog(CompleteSqlSqlFormatPlugin.class); @Override public Object intercept(Invocation invocation) throws Throwable { Object target = invocation.getTarget(); if (target instanceof RoutingStatementHandler) { try { MetaObject metaObject = SystemMetaObject.forObject(target); Configuration configuration = (Configuration) metaObject.getValue("delegate.configuration"); MybatisConfiguration mc = (MybatisConfiguration) configuration; List<ISqlParser> sqlParserList = new ArrayList<>(); if (mc.getSqlParserAutoFill()) { sqlParserList.addAll(SqlParserHelper.getSqlParserList(mc.isBlockAttack())); } if (sqlParserList.size() > 0) { GlobalConfig globalConfig = GlobalConfigUtils.getGlobalConfig(configuration); ISqlParser sqlParser = null; String tenantHandlerSql = null; if (StringUtils.isNotBlank(globalConfig.getTenantHandlerSql()) && StringUtils.isNotBlank(globalConfig.getTenantIdColumn()) && !globalConfig.isExcludeTenantTable()) { tenantHandlerSql = globalConfig.getTenantHandlerSql(); sqlParser = SqlParserHelper.getTenantParser(globalConfig.getTenantIdColumn(), tenantHandlerSql); } SqlInfo sqlInfo = SqlParserHelper.getOptimizeCountSql(mc.isCountStyle()); for (ISqlParser iSqlParser : sqlParserList) { if (sqlParser != null) { iSqlParser.processIntervalSql(tenantHandlerSql, sqlInfo.getSql(), configuration); } iSqlParser.parser(metaObject.getValue("delegate.boundSql.sql").toString()); } } } catch (Exception e) { logger.error("prepar intercept error", e); } } return invocation.proceed(); } @Override public Object plugin(Object target) { return Plugin.wrap(target, new CompleteSqlSqlFormatInterceptor()); } @Override public void setProperties(Properties properties) { // do nothing. }
}
```
这里,我们实现了一个
CompleteSqlSqlFormatPlugin
类,同时该类还继承了 MybatisPlus 的DefaultSqlInjector
类,这样该插件就可以注册到 MybatisPlus 中。在该插件中,我们实现了插件的三个方法:intercept
、plugin
和setProperties
。其中,intercept
方法用于判断当前 StatementHandler 类型是否为 RoutingStatementHandler,如果是,则调用我们自己实现的 SQL 格式化器;而plugin
方法用于包装目标对象,返回一个它的代理对象。最后,我们将自己的插件注册到 MybatisPlus 中。 -
最后,我们需要在 application.yml 或 application.properties 中启用插件:
yaml
mybatis-plus:
global-config:
sql-injector: cn.edu.zzti.plugins.CompleteSqlSqlFormatPlugin
# 其他配置
configuration:
# 其他配置
好了,至此,我们已经成功地实现了 MybatisPlus 打印完整 SQL 不带问号的功能。相比于方法一中使用日志输出完整的 SQL,这种方法更加灵活,能够更好地适应不同场景下的需求。
参考文献:
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:mybatisplus打印完整sql不带问号 - Python技术站