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