1. 程式人生 > >mybatis怎麼打印出sql,我被誤導了很多年

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,就可以了。