源码分析之spring-JdbcTemplate日志打印sql语句

时间:2021-10-17 19:46:54

对于开源的项目来说的好处就是我们遇到什么问题可以通过看源码来解决。

比如近期有个同事问我说,为啥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语句。

 public <T> T execute(PreparedStatementCreator psc, PreparedStatementCallback<T> action)
throws DataAccessException { Assert.notNull(psc, "PreparedStatementCreator must not be null");
Assert.notNull(action, "Callback object must not be null");
if (logger.isDebugEnabled()) {
String sql = getSql(psc);
logger.debug("Executing prepared SQL statement" + (sql != null ? " [" + sql + "]" : ""));
} Connection con = DataSourceUtils.getConnection(getDataSource());
PreparedStatement ps = null;
try {
Connection conToUse = con;
if (this.nativeJdbcExtractor != null &&
this.nativeJdbcExtractor.isNativeConnectionNecessaryForNativePreparedStatements()) {
conToUse = this.nativeJdbcExtractor.getNativeConnection(con);
}
ps = psc.createPreparedStatement(conToUse);
applyStatementSettings(ps);
PreparedStatement psToUse = ps;
if (this.nativeJdbcExtractor != null) {
psToUse = this.nativeJdbcExtractor.getNativePreparedStatement(ps);
}
T result = action.doInPreparedStatement(psToUse);
handleWarnings(ps);
return result;
}
catch (SQLException ex) {
// Release Connection early, to avoid potential connection pool deadlock
// in the case when the exception translator hasn't been initialized yet.
if (psc instanceof ParameterDisposer) {
((ParameterDisposer) psc).cleanupParameters();
}
String sql = getSql(psc);
psc = null;
JdbcUtils.closeStatement(ps);
ps = null;
DataSourceUtils.releaseConnection(con, getDataSource());
con = null;
throw getExceptionTranslator().translate("PreparedStatementCallback", sql, ex);
}
finally {
if (psc instanceof ParameterDisposer) {
((ParameterDisposer) psc).cleanupParameters();
}
JdbcUtils.closeStatement(ps);
DataSourceUtils.releaseConnection(con, getDataSource());
}
}

以上我们说的只是个例子,其实这个猜一下也大概知道应该是日志级别的配置问题。通过这个小问题我只想说的是,有时候遇到问题,不一定急着去问朋友、同事,或者google,百度,何况google那么难上去。开源的程序的话自己看下源码,问题说不行就解决了。这样对自己来说好处多多