mybatis 打印SQL语句

1,310 阅读1分钟
  • 网上有很多种办法,最简单的办法是设置root为debug,但是粒度不够细,下面这种办法可以控制粒度;
<configuration>
    <!-- 使用mybatis的@Mapper注解,name就配置成注解的类的路径 -->
  	<logger name="xx.xx.mapper" level="DEBUG"/>
   <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>[%d{yyyy-MM-dd HH:mm:ss:SSS}] %level %thread %logger{36}:%L- %msg%n</pattern>
            <charset class="java.nio.charset.Charset">UTF-8</charset>
        </encoder>
    </appender>
  
   <root level="INFO">
        <appender-ref ref="CONSOLE" />
    </root>

</configuration>
  • 下面是打印SQL的类,但是通过代理后,我们在日志中看到的是自己的类名

 打印SQL的类:org.apache.ibatis.logging.jdbc.ConnectionLogger
 打印参数的类:org.apache.ibatis.logging.jdbc.PreparedStatementLogger
 

系统启动时,会自动扫描到xml中所有的配置,root为根节点,是其他的所有类的父级节点,如果为定义,则默认继承自root的配置

   // 设置rootLogger
    public LoggerContext() {
      super();
      this.loggerCache = new ConcurrentHashMap<String, Logger>();
      this.loggerContextRemoteView = new LoggerContextVO(this);
      this.root = new Logger(Logger.ROOT_LOGGER_NAME, null, this);
      this.root.setLevel(Level.DEBUG);
      loggerCache.put(Logger.ROOT_LOGGER_NAME, root);
      initEvaluatorMap();
      size = 1;
      this.frameworkPackages = new ArrayList<String>();
  }

    @Override
  public final Logger getLogger(final String name) {
		.... 省略部分代码
/**
  自循环,根据当前自定义@mapper接口类的包路径和logback配置
件中的配置的包路径进行逐步的匹配,直到找到配置文件中的定义,如果最后还是找不
到则使用root的定义;
**/
	  String childName;
      while (true) {
          int h = LoggerNameUtil.getSeparatorIndexOf(name, i);
          if (h == -1) {
              childName = name;
          } else {
              childName = name.substring(0, h);
          }
          // move i left of the last point
          i = h + 1;
          synchronized (logger) {
              childLogger = logger.getChildByName(childName);
              if (childLogger == null) {
		         //找到了logger,返回logger
                  childLogger = logger.createChildByName(childName);
                  loggerCache.put(childName, childLogger);
                  incSize();
              }
          }
          logger = childLogger;
          if (h == -1) {
              return childLogger;
          }
      }

}

当level设置成debug时,【effectiveLevelInt】属性就是10000

当level设置成info时,【effectiveLevelInt】属性就是20000

最终Log会设置到MappedStatement类的statementLog属性中

在执行SQL语句时,会调用下面的代码

  protected Connection getConnection(Log statementLog) throws SQLException {
    Connection connection = transaction.getConnection();
    //判断是否使用debug
    if (statementLog.isDebugEnabled()) {
      // 最终会调用ConnectionLogger.invoke()方法
      return ConnectionLogger.newInstance(connection, statementLog, queryStack);
    } else {
      return connection;
    }
  }  
  public boolean isDebugEnabled(Marker marker) {
      final FilterReply decision = callTurboFilters(marker, Level.DEBUG);
        if (decision == FilterReply.NEUTRAL) {
        //通过:effectiveLevelInt <= 10000 的返回值来判断是否使用日志打印
            return effectiveLevelInt <= Level.DEBUG_INT;
        } else if (decision == FilterReply.DENY) {
            return false;
        } else if (decision == FilterReply.ACCEPT) {
            return true;
        } else {
            throw new IllegalStateException("Unknown FilterReply value: " + decision);
        }
    }

最终控制台打印SQL语句

xx.mapper.xx:159- ==>  Preparing: select ***
xx.mapper.xx:159- ==>  Parameters: