Mybatis不一樣版本sql日誌打印

工做中常常但願打印mybatis執行sql的debug日誌,上網找到的各類配置都不生效,這是由於mybatis版本不一樣日誌打印方法也不一樣,下面談談開啓日誌的經驗。java

第一種方法,是把全部的日誌都放開, 而後從中選取本身須要的部分;sql

第二種方法,從原理層解決是看mybatis源代碼,找到打日誌的代碼,這裏選取兩個版本觀看:mybatis

  1. 3.0.1版,app

public class PreparedStatementLogger extends BaseJdbcLogger implements InvocationHandler {

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

    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());
                }
               ......//省略
            } 
        } catch (Throwable t) {
            throw ExceptionUtil.unwrapThrowable(t);
        }
    }
}

看PreparedStatementLogger的invoke方法,log是經過java.sql.PreparedStatement初始化的日誌,因此log4j配置方式爲:log4j.logger.java.sql.PreparedStatement=DEBUGui

 2. 3.2.8版,this

ConnectionLogger和PreparedStatementLogger均繼承至BaseJdbcLogger,看BaseJdbcLogger的debug方法知道其log是構造方法傳過來的spa

public abstract class BaseJdbcLogger {
    protected Log statementLog;
    public BaseJdbcLogger(Log log, int queryStack) {
        this.statementLog = log;
        if (queryStack == 0)
            queryStack = 1;
        this.queryStack = queryStack;
    }
    protected void debug(String text, boolean input) {
        if (statementLog.isDebugEnabled()) {
            statementLog.debug(prefix(input) + text);
        }
    }
}

跟蹤調用棧找到該log實例是MappedStatement裏面傳過來的,看MappedStatement構造:debug

public final class MappedStatement {
    private MappedStatement() {
        // constructor disabled
    }
    public static class Builder {
        private MappedStatement mappedStatement = new MappedStatement();

        public Builder(Configuration configuration, String id, SqlSource sqlSource, SqlCommandType sqlCommandType) {
            mappedStatement.configuration = configuration;
            mappedStatement.id = id;//mappedStatement的惟一標識,namespace+id
            mappedStatement.sqlSource = sqlSource;
            mappedStatement.statementType = StatementType.PREPARED;
            mappedStatement.parameterMap = new ParameterMap.Builder(configuration, "defaultParameterMap", null,
                    new ArrayList<ParameterMapping>()).build();
            mappedStatement.resultMaps = new ArrayList<ResultMap>();
            mappedStatement.timeout = configuration.getDefaultStatementTimeout();
            mappedStatement.sqlCommandType = sqlCommandType;
            mappedStatement.keyGenerator = configuration.isUseGeneratedKeys()
                    && SqlCommandType.INSERT.equals(sqlCommandType) ? new Jdbc3KeyGenerator() : new NoKeyGenerator();
            String logId = id;
            if (configuration.getLogPrefix() != null)//能夠加前綴
                logId = configuration.getLogPrefix() + id;
            //這邊是構造log的地方
            mappedStatement.statementLog = LogFactory.getLog(logId);
            mappedStatement.lang = configuration.getDefaultScriptingLanuageInstance();
        }
    }
}

看log是根據MappedStatement的id建立的,這裏的id是namespace+id,因此log4j的寫法應該是:日誌

log4j.logger.com.xxx.mapper=DEBUGcode

com.xxx.mapper是每一個業務的包名,若是業務不少,就每一個須要打印日誌的包路徑都寫一遍,麻煩!看到上面代碼還有一個關鍵元素configuration.getLogPrefix(),這個前綴是在解析配置的時候獲取的,配置這個前綴就能夠因此log用一個logger配置。以下:

<settings>
    <setting name="logPrefix" value="abcdefg" />
</settings>

log4j.logger.abcdefg=DEBUG

相關文章
相關標籤/搜索