mybatis怎麼打印出sql,我被誤導了很多年
關於mybatis怎麼打印出sql這個問題,可以百度一下,很多答案都有類似這樣的答案:
就是把java.sql.*,com.ibatis等的日誌級別都配置成debug的,也許這麼配置與預設的info配置相比真的有效果,把sql打印出來了。可是我今天才發現,列印sql與這些java.sql,com.ibatis包半毛錢關係都沒有。至少我除錯的mybatis-3.3.0.jar就是這樣的,因為它列印日誌的物件是org.apache.ibatis.logging.slf4j.Slf4jImpl(statementLog),而statementLog又是在系統啟動時,掃描的logId(如com.**.Mapper.query)作為其構造引數的。是否列印日誌就是這個引數是否與log4j.xml,與log4j.properties裡的log4j.logger匹配來決定的。下面通過原始碼來分析整個過程:
1.statementLog是否為debug,來決定是否列印sql
程式碼:org.apache.ibatis.executor.SimpleExecutor
如果進入上圖裡建立ConnectionLogger物件的程式碼,就可執行真正列印日誌的程式碼。如下圖
類:org.apache.ibatis.logging.jdbc.BaseJdbcLogger
程式碼行:ConnectionLogger(BaseJdbcLogger).debug(String, boolean) line: 141
2.statementLog的注入
statementLog來源於MappendStatement
而MappendStatement是org.apache.ibatis.session.Configuration註冊進去的。
再看MappendStatement的構造過程是如何建立Log的。
類:org.apache.ibatis.mapping.MappedStatement.Builder
LogFactory.getLog(xx)這行程式碼再熟悉不過了吧,從這裡的值來看,是不是跟什麼java.sql、com.ibatis沒有半毛錢關係。
mybatis用的日誌框架確實足夠強大,無論我們是用slf4j還是common-logger,它都能用起來,這是什麼麼呢?
看下類:org.apache.ibatis.logging.LogFactory:
在載入這個類時會執行上面的靜態程式碼塊,這裡會依次去嘗試各種日誌框架的實現。嘗試程式碼如下:
如果有一個成功,則logConstructor就被例項化,不為空了,後面的就沒有機會執行了。從這裡的程式碼我又學了一招,怎麼相容客戶端不同的jar實現,即使客戶端沒有其中的一個實現jar包,程式碼也不會錯。
最後還是回答一下標題,如何列印sql呢,比如我上面的程式碼就配置一下log4j.logger.com.helijia.search=DEBUG,就可以了。