工做中常常但願打印mybatis執行sql的debug日誌,上網找到的各類配置都不生效,這是由於mybatis版本不一樣日誌打印方法也不一樣,下面談談開啓日誌的經驗。java
第一種方法,是把全部的日誌都放開, 而後從中選取本身須要的部分;sql
第二種方法,從原理層解決是看mybatis源代碼,找到打日誌的代碼,這裏選取兩個版本觀看:mybatis
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