Spring JDBC最佳實踐(2)
使用DataSourceUtils進行Connection的管理
由
上節代碼可知,JdbcTemplate在獲取Connection的時候,并不是直接調用DataSource的getConnection(),而是調用了如下的代碼:
Connection con = DataSourceUtils.getConnection(getDataSource());為什么要這么做呢?
實際上,如果對于一個功能帶一的JdbcTemplate來說,調用如下的代碼就夠了:
Connection con = dataSource.getConnection();只不過,spring所提供的JdbcTemplate要關注更多的東西,所以,在從dataSource取得連接的時候,需要多做一些事情。
org.springframework.jdbc.datasource.DataSourceUtils所提供的方法,用來從指定的DataSource中獲取或者釋放連接,它會將取得的Connection綁定到當前的線程,以便在使用Spring所提供的統一事務抽象層進行事務管理的時候使用。
為什么要使用NativeJdbcExtractor
在execute()方法中可以看到:
if (this.nativeJdbcExtractor != null && this.nativeJdbcExtractor.isNativeConnectionNecessaryForNativeStatements()) { conToUse = this.nativeJdbcExtractor.getNativeConnection(con); }
if (this.nativeJdbcExtractor != null) { stmtToUse = this.nativeJdbcExtractor.getNativeStatement(stmt); }通過該處理,獲取的將是相應的驅動程序所提供的實現類,而不是相應的代理對象。
JdbcTemplate內部定義了一個NativeJdbcExtractor類型的實例變量:
/** Custom NativeJdbcExtractor */ private NativeJdbcExtractor nativeJdbcExtractor;當我們想用驅動對象所提供的原始API的時候,可以通過JdbcTemplate的如下代碼:
public void setNativeJdbcExtractor(NativeJdbcExtractor extractor) { this.nativeJdbcExtractor = extractor; }這樣將會獲取真正的目標對象而不是代理對象。
spring默認提供面向Commons DBCP、C3P0、Weblogic、Websphere等數據源的NativeJdbcExtractor的實現類: CommonsDbcpNativeJdbcExtractor:為Jakarta Commons DBCP數據庫連接池所提供的NativeJdbcExtractor實現類 C3P0NativeJdbcExtractor:為C3P0數據庫連接池所提供的NativeJdbcExtractor實現類 WebLogicNativeJdbcExtractor:為Weblogic所準備的NativeJdbcExtractor實現類
WebSphereNativeJdbcExtractor:為WebSphere所準備的NativeJdbcExtractor實現類
控制JdbcTemplate的行為 JdbcTemplate在使用Statement或者PreparedStatement等進行具體的數據操作之前,會調用如下的代碼:
protected void applyStatementSettings(Statement stmt) throws SQLException { int fetchSize = getFetchSize(); if (fetchSize > 0) { stmt.setFetchSize(fetchSize); } int maxRows = getMaxRows(); if (maxRows > 0) { stmt.setMaxRows(maxRows); } DataSourceUtils.applyTimeout(stmt, getDataSource(), getQueryTimeout()); }
這樣便可以設置Statement每次抓取的行數 等等。
SQLException到DataAccessException的轉譯 因為JdbcTemplate直接操作的是JDBC API,所以它需要捕獲在此期間可能發生的SQLException,處理的宗旨是將SQLException 轉譯到spring的數據訪問異常層次體系,以統一數據訪問異常的處理方式,這個工作主要是交給了SQLExceptionTranslator,該 接口的定義如下:
package org.springframework.jdbc.support;import java.sql.SQLException;
import org.springframework.dao.DataAccessException;
/**
*
- @author Rod Johnson
- @author Juergen Hoeller
- @see org.springframework.dao.DataAccessException */ public interface SQLExceptionTranslator {
DataAccessException translate(String task, String sql, SQLException ex);
}</pre>
該接口有兩個主要的實現類,SQLErrorCodeSQLExceptionTranslator和SQLStateSQLExceptionTranslator,如下所示: