最近的項目使用的是舊的ibatis2.x版本,有時候為了方便調(diào)試,想輸出SQL執(zhí)行的語句和參數(shù)。我記得應(yīng)該有某些logger的日志級別修改為DEBUG就可以看到。當(dāng)然為了方便可以直接在log4j(如果使用log4j的話)的root日志級別修改為DEBUG,并且輸出appender的接受級別修改為DEBUG就可以了。這樣是可以看到日志信息(SQL/參數(shù))等,但是同時也輸出了過多的其它logger信息,顯然在一個稍微大一點的系統(tǒng)里面debug的信息應(yīng)該都是非常多的,不說別的,光是spring的日志就夠好多頁了。
為了解決過多的日志,翻出ibatis源碼,看了下。ibatis的執(zhí)行流程大致是這樣的。
執(zhí)行步驟如下:
- 通過SqlMapClient執(zhí)行query/execute操作;
- 打開一個SqlMapSession會話(openSession());
- 設(shè)置數(shù)據(jù)源(DataSource)或者外部給的java.sql.Connection;
- 通過java.sql.Connection和外部給的Transaction(如果有的話)構(gòu)造事務(wù);
- 如果java.sql.Connection的日志級別為DEBUG,構(gòu)造一個帶日志記錄的ConnectionLogProxy(是java.sql.Connection的一個Proxy);
- 在ConnectionLogProxy中構(gòu)造一個帶日志記錄的PreparedStatementLogProxy(是java.sql.PreparedStatement的一個Proxy);
- 執(zhí)行java.sql.Connection中的操作(如果是ConnectionLogProxy就記錄連接日志);
- 執(zhí)行java.sql.PreparedStatement操作(如果是PreparedStatementLogProxy就記錄操作記錄,包括SQL信息)。
我們看三段代碼:
第一段代碼可以看到,要想記錄日志的前提是java.sql.Connection的logger的級別是DEBUG或者更低。
第二段代碼可以看到,要想記錄PreparedStatement的日志,那么比如滿足上述第一段代碼的條件。這里會記錄連接Connection打開的相關(guān)信息,比如是否是新開的Connection,這可以從id中分析出。ConnectionLogProxy是java.sql.Connection的一個Proxy實現(xiàn)。
第三段代碼可以看到,記錄PreparedStatement的日志(SQL/參數(shù))需要java.sql.PreparedStatement的logger的級別是DEBUG或者更低。這里會記錄執(zhí)行的SQL、參數(shù)、參數(shù)類型等。PreparedStatementLogProxy是java.sql.PreparedStatement的一個Proxy實現(xiàn)。
因此要顯示執(zhí)行的SQL、參數(shù)、參數(shù)類型以及連接信息等需要配置兩個日志級別為DEBUG或者更低。
對于log4j來說增加以下兩項就可以了(如果是properties文件的話,xml修改對應(yīng)規(guī)則):
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
上面第二段代碼中如果看的夠仔細(xì)的話可以發(fā)現(xiàn)有一個ResultSetLogProxy的代理,配置這個相關(guān)的日志級別后可以輸出執(zhí)行結(jié)果信息。有興趣的可以看看吧。