1. 程式人生 > >(轉)logback 打印Mybitis中的sql執行過程

(轉)logback 打印Mybitis中的sql執行過程

values tis nav ole 決定 ret 閱讀 factor ins

閱讀目錄

  • 1 不同版本的Mybitis對應不同的控制策略

場景:在程序開發過程中經常需要跟蹤程序中sql語句的執行過程,在控制臺打印出sql語句和對應的參數傳遞就能夠更快的定位錯誤!

原文出處:http://www.cnblogs.com/beiyeren/p/4196134.html

這裏所采用的日誌框架為logback

1 不同版本的Mybitis對應不同的控制策略

1.1 myBatis3.0.6左右的版本時

打印sql的時候只需要配置如下屬性:

<logger name="java.sql.Connection" level="DEBUG" />
<logger name="java.sql.Statement" level="DEBUG" />
<logger name="java.sql.PreparedStatement" level="DEBUG" />

源碼解析:

PreparedStatementLogger裏面看這個log.isDebugEnabled()
public Object invoke(Object proxy, Method method, Object[] params) throws Throwable {
    try {
      if (EXECUTE_METHODS.contains(method.getName())) {
        if (log.isDebugEnabled()) {
          log.debug("==>  Executing: " + removeBreakingWhitespace(sql));
          log.debug("==> Parameters: " + getParameterValueString());
        }
        clearColumnInfo();
        if ("executeQuery".equals(method.getName())) {
          ResultSet rs = (ResultSet) method.invoke(statement, params);
          if (rs != null) {
            return ResultSetLogger.newInstance(rs);
          } else {
            return null;
          }
        } else {
          return method.invoke(statement, params);
        }
      }

這個log定義的是PreparedStatement

private static final Log log = LogFactory.getLog(PreparedStatement.class);

1.2 在myBatis3.2.7左右版本(以上也可以)

只需要簡單的兩步即可!

更改了打印Sql的模式,它將sql打印細化到了每一個mapperStatement的每一個方法上。

如果你打算有一個全局配置打印所有的sql,則需要如下配置

在mybatis的configuration中增加setting配置

<settings>
        <setting name="logPrefix" value="dao."/>
</settings>

然後增加配置

<logger name="dao" level="DEBUG"/>

源碼解析:

ConnectionLogger
public Object invoke(Object proxy, Method method, Object[] params)
      throws Throwable {
    try {
      if (Object.class.equals(method.getDeclaringClass())) {
        return method.invoke(this, params);
      }    
      if ("prepareStatement".equals(method.getName())) {
        if (isDebugEnabled()) {
          debug(" Preparing: " + removeBreakingWhitespace((String) params[0]), true);
        }        
        PreparedStatement stmt = (PreparedStatement) method.invoke(connection, params);
        stmt = PreparedStatementLogger.newInstance(stmt, statementLog, queryStack);
        return stmt;
      }

其中的isDebugEnabled()指的是

protected boolean isDebugEnabled() {
    return statementLog.isDebugEnabled();
}

註意這裏的statementLog,看SimpleExecutor的prepareStatement(handler, ms.getStatementLog());

public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
    Statement stmt = null;
    try {
      Configuration configuration = ms.getConfiguration();
      StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
      stmt = prepareStatement(handler, ms.getStatementLog());
      return handler.<E>query(stmt, resultHandler);
    } finally {
      closeStatement(stmt);
    }
  }

這個statementLog是ms.getStatementLog()而來的。而MappedStatement的StatementLog

String logId = id;
 if (configuration.getLogPrefix() != null) logId = configuration.getLogPrefix() + id;
 mappedStatement.statementLog = LogFactory.getLog(logId);

這裏可以看到,logPrefix決定了所有log前綴,所以只需要配置logPrefix就行了

(轉)logback 打印Mybitis中的sql執行過程