Springboot+Mybatis+Oracle项目中,log4j绿色输出console无占位符的SQL

问题背景和目的:

我所尝试过的解决方法(没能行得通的)

最终可行的解决方法

     1、pom.xml添加log4j的依赖

     2、src/main/resources下配置mybatis-config.xml

     3、src/main/resources下配置logj4j.properties

     4、进行部分代码覆盖重写,将参数填充至占位符?得到最终想要的结果


问题背景和目的:

问题背景照常还是要说一下的,因为不同的问题,解决方案往往是不同的。

想必很多开发者在debug一个业务的SQL时,参数太多往往降低开发效率,更容易导致出错,这篇博客刚好能提出一个这样的思路,最低成本的解决这个问题,也就是“绿色”方法。讲道理,这个方法应该适用于所有使用log4j作为日志输出的项目开发。

我要达到的目的如下:

==> Preparing: SELECT a."oid",  a."delflag" FROM table a WHERE a."delflag" = 1 AND a."oid" = 1

<== Total: 0

我所尝试过的解决方法(没能行得通的)

网上有过加入log4j、slf4j-api全家桶这样成功的案例,我都配置好了,最后报not support oracle driver 1.0,折腾我将近7小时也未能解决这个问题

我尝试通过(网络上寻找的几个解决方法):

①添加tomcat-jdbc的依赖不得解;

②报错原因是因为数据库驱动不支持,更换了ojdbc6、druid版本后依然不得解;

③重新更换pom.xml中所有引入的log4j全家桶版本未网络上一致不得解(网络上的解决方法大多应用于MySQL);

https://www.oschina.net/question/3739295_2308736中就是我的一些基本配置,通过询问网络也不得解

作罢,我觉得我应该换个思路,之前有瞟过一眼接下来的解决方法,觉得有点野路子,就没去测试。现在有点后悔没用思维导图工具来解决问题了,那样解决思路会清晰的很多,我这也算站在巨人的肩膀上了。

最终可行的解决方法

1、pom.xml添加log4j的依赖

springboot项目与传统的springMVC+Maven有点不同的是,我只添加了这一个log4j的依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

2、src/main/resources下配置mybatis-config.xml

<configuration>
	<!--
	    配置文件中各配置的位置必须符合要求,否则会报错,顺序如下:
	    properties?, settings?,
	    typeAliases?, typeHandlers?,
	    objectFactory?,objectWrapperFactory?,
	    plugins?,
	    environments?, databaseIdProvider?, mappers?
	-->
    <settings>
        <!-- 日志输出 -->
        <setting name="logImpl" value="LOG4J2" />
        <!-- mapper.xml中替代jdbctype的配置 -->
        <setting name="jdbcTypeForNull" value="NULL" />
    </settings>
</configuration>

3、src/main/resources下配置logj4j.properties

由于对log4j的研究不是很深,所以这些配置中可能存在错误和冗余项,日后再修改

#logFile
log4j.rootLogger=DEBUG,Console
#Console    
log4j.appender.Console=org.apache.log4j.ConsoleAppender  
log4j.appender.console.Threshold=INFO
log4j.appender.console.ImmediateFlush=true
log4j.appender.Console.Target=System.out
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%-5p %d{yyyy-MM-dd HH:mm:ss}[%t] %l: %x%m%n

# 日志文件(logFile)
log4j.appender.logFile=org.apache.log4j.FileAppender
log4j.appender.logFile.Threshold=DEBUG

log4j.logger.org.apache=ERROR
log4j.logger.org.mybatis=ERROR  
log4j.logger.org.springframework=ERROR  
#这个需要 
log4j.logger.log4jdbc.debug=ERROR  

log4j.logger.jdbc.audit=ERROR
log4j.logger.jdbc.resultset=ERROR  
#这个打印SQL语句非常重要  
log4j.logger.jdbc.sqlonly=DEBUG
log4j.logger.jdbc.sqltiming=ERROR 
log4j.logger.jdbc.connection=FATAL

数据库的配置可能有些朋友需要,这里就不给出怎么配置druid了。

spring:
    datasource:
      username: system
      password: 123456
      url: jdbc:oracle:thin:@//127.0.0.1:1521/orcl
      driver-class-name: oracle.jdbc.OracleDriver
      timeBetweenEvictionRunsMillis: 600000
      testOnBorrow: true
      testOnReturn: false
      testWhileIdle: true
      validationQuery: SELECT 1 FROM DUAL     # Oracle的连接必须指定一个表名,DUAL是个默认的
      validationQueryTimeout: 300000
      filters: stat,wall,log4j2
      initialSize: 5
      minEvictableIdleTimeMillis: 300000
      minIdle: 5
      maxActive: 10
      maxOpenPreparedStatements: 10
      maxWait: 600000
      poolPreparedStatements: false      # 性能开关,可缓存preparedStatement(PSCache),因为Oracle支持游标

到目前的配置,log4j输出的语句应该类似于

==>  Preparing: SELECT a."oid",  a."delflag" FROM table a WHERE a."delflag" = ? AND a."oid" = ?
==>  Parameters: 0(Long), 1(Long)
<==  Total: 0

4、进行部分代码覆盖重写,将参数填充至占位符?得到最终想要的结果

由于不懂log4j,以下部分根据一佚名码友提供的思路改写

①随便找个地方import org.apache.ibatis.logging.jdbc.BaseJdbcLogger,从而可打开复制全部内容;

②在src/main/java新建一个目录org.apache.ibatis.logging.jdbc,并new一个class粘贴刚刚复制的代码;

③找到protected void debug(String text, boolean input) 这个方法↓

protected void debug(String text, boolean input) {
    if (statementLog.isDebugEnabled()) {
        statementLog.debug(prefix(input) + text);
    }
}

④将它修改为:(text:是需要打印的文本),这个逻辑可以非常清晰体现思路。(后面有修改201907241912)

protected void debug(String text, boolean input) {
    text = text.trim();
    if (statementLog.isDebugEnabled()) {
	if (text.startsWith("Preparing:")) {
		sql = text.substring(text.indexOf(":") + 1);
		return;
	}
	if (text.startsWith("Parameters:")) {
		String temp = text.substring(text.indexOf(":") + 1);
		String[] split = temp.split(",");
		if (split != null & split.length > 0) {
			for (String string2 : split) {
				String s = string2.trim();
				sql = sql.replaceFirst("\\?", s.substring(0, s.indexOf("(")));
			}
		}
		text = "Preparing:" + sql;
		sql = "";
	}
	statementLog.debug(prefix(input) + text);
    }
}

======修改为:=========
protected void debug(String text, boolean input) {
    text = text.trim();
    if (statementLog.isDebugEnabled()) {
    if (text.startsWith("Preparing:")) {
    sql = text.substring(text.indexOf(":") + 1);
        return;
    }
    if (text.startsWith("Parameters:")) {
        String temp = text.substring(text.indexOf(":") + 1);
        String[] split = temp.split(",");
        if (split != null & split.length > 0) {
            for (String string2 : split) {
                String s = string2.trim();
                String replaceText = " ";
                if(s.indexOf("(") == -1) {
                    //如果参数是null,是没有类型的,也就没有括号,如:33(Long),  null,
                    if("null".equals(s))
                        replaceText = "NULL";
                    }else
                        replaceText = s.substring(0, s.indexOf("("));
                    sql = sql.replaceFirst("\\?", replaceText);
                }
            }
            text = "Preparing:" + sql;
            sql = "";
        }
        statementLog.debug(prefix(input) + text);
    }
}

⑤调试一下可以看到成功了

==> Preparing: SELECT a."oid",  a."delflag" FROM table a WHERE a."delflag" = 1 AND a."oid" = 1

<== Total: 0

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值