源碼分析之spring-JdbcTemplate日志打印sql語句


對於開源的項目來說的好處就是我們遇到什么問題可以通過看源碼來解決。

比如近期有個同事問我說,為啥JdbcTemplate中只有在Error的時候才打印出sql語句呢。我一想,這和log的配置有關系吧。 我們的系統中使用了slf4j作為日志管理工具,之前也好像看到過項目工程中配置的日志級別是error的,所以當代碼錯誤時打印出sql語句應該也屬於正常。但是想要正常運行時也打印出sql語句,相比和配置有關,但是應該配置那個級別呢? 應該要看下JdbcTemplate的源碼怎么寫的,這樣可快速定位配置那個日志級別(當然你可以一個一個的試)。在maven工程內看源碼及其方便(個人認為用maven的唯一好處)。

在eclipse中通過快捷鍵(windows系統中默認快捷鍵 ctrl+shift+T)打開Open Type窗口,輸入JdbcTemplate后自動搜索到該類后點擊進入,如果未下載過源碼,maven會自動下載。在源碼中找到我們經常用的execute(PreparedStatementCreator psc, PreparedStatementCallback<T> action)這個方法,然后看如下源碼的第6、7、8行,使用了if(logger.isDebugEnabled)這個判斷,意思是如果logger的日志級別為debug的,那么進入這個語句塊,第7行獲取sql的內容,第八行通過logger.debug將內容輸出。由此可見我們需要配置debug級別的。然后在logger的配置文件中error修改為debug,正常輸出sql語句。

 1 public <T> T execute(PreparedStatementCreator psc, PreparedStatementCallback<T> action)
 2             throws DataAccessException {
 3 
 4         Assert.notNull(psc, "PreparedStatementCreator must not be null");
 5         Assert.notNull(action, "Callback object must not be null");
 6         if (logger.isDebugEnabled()) {  7             String sql = getSql(psc);  8             logger.debug("Executing prepared SQL statement" + (sql != null ? " [" + sql + "]" : ""));  9  } 10 
11         Connection con = DataSourceUtils.getConnection(getDataSource());
12         PreparedStatement ps = null;
13         try {
14             Connection conToUse = con;
15             if (this.nativeJdbcExtractor != null &&
16                     this.nativeJdbcExtractor.isNativeConnectionNecessaryForNativePreparedStatements()) {
17                 conToUse = this.nativeJdbcExtractor.getNativeConnection(con);
18             }
19             ps = psc.createPreparedStatement(conToUse);
20             applyStatementSettings(ps);
21             PreparedStatement psToUse = ps;
22             if (this.nativeJdbcExtractor != null) {
23                 psToUse = this.nativeJdbcExtractor.getNativePreparedStatement(ps);
24             }
25             T result = action.doInPreparedStatement(psToUse);
26             handleWarnings(ps);
27             return result;
28         }
29         catch (SQLException ex) {
30             // Release Connection early, to avoid potential connection pool deadlock
31             // in the case when the exception translator hasn't been initialized yet.
32             if (psc instanceof ParameterDisposer) {
33                 ((ParameterDisposer) psc).cleanupParameters();
34             }
35             String sql = getSql(psc);
36             psc = null;
37             JdbcUtils.closeStatement(ps);
38             ps = null;
39             DataSourceUtils.releaseConnection(con, getDataSource());
40             con = null;
41             throw getExceptionTranslator().translate("PreparedStatementCallback", sql, ex);
42         }
43         finally {
44             if (psc instanceof ParameterDisposer) {
45                 ((ParameterDisposer) psc).cleanupParameters();
46             }
47             JdbcUtils.closeStatement(ps);
48             DataSourceUtils.releaseConnection(con, getDataSource());
49         }
50     }

以上我們說的只是個例子,其實這個猜一下也大概知道應該是日志級別的配置問題。通過這個小問題我只想說的是,有時候遇到問題,不一定急着去問朋友、同事,或者google,百度,何況google那么難上去。開源的程序的話自己看下源碼,問題說不行就解決了。這樣對自己來說好處多多


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM