Spring JDBC最佳实践(2)
fmms
13年前
<b>使用DataSourceUtils进行Connection的管理</b> <br /> 由 <a href="http://www.open-open.com/lib/view/open1325676513734.html" target="_blank">上节代码</a>可知,JdbcTemplate在获取Connection的时候,并不是直接调用DataSource的getConnection(),而是调用了如下的代码: <br /> <pre class="brush:java; toolbar: true; auto-links: false;"> Connection con = DataSourceUtils.getConnection(getDataSource());</pre> <p></p> 为什么要这么做呢? <br /> 实际上,如果对于一个功能带一的JdbcTemplate来说,调用如下的代码就够了: <br /> <pre class="brush:java; toolbar: true; auto-links: false;"> Connection con = dataSource.getConnection();</pre> <p></p> 只不过,spring所提供的JdbcTemplate要关注更多的东西,所以,在从dataSource取得连接的时候,需要多做一些事情。 <br /> <p>org.springframework.jdbc.datasource.DataSourceUtils所提供的方法,用来从指定的DataSource中获取或者释放连接,它会将取得的Connection绑定到当前的线程,以便在使用Spring所提供的统一事务抽象层进行事务管理的时候使用。</p> <p><b>为什么要使用NativeJdbcExtractor</b><br /> 在execute()方法中可以看到:<br /> </p> <pre class="brush:java; toolbar: true; auto-links: false;"> if (this.nativeJdbcExtractor != null && this.nativeJdbcExtractor.isNativeConnectionNecessaryForNativeStatements()) { conToUse = this.nativeJdbcExtractor.getNativeConnection(con); }</pre> <p></p> <pre class="brush:java; toolbar: true; auto-links: false;">if (this.nativeJdbcExtractor != null) { stmtToUse = this.nativeJdbcExtractor.getNativeStatement(stmt); }</pre> <p></p> 通过该处理,获取的将是相应的驱动程序所提供的实现类,而不是相应的代理对象。 <br /> JdbcTemplate内部定义了一个NativeJdbcExtractor类型的实例变量: <br /> <pre class="brush:java; toolbar: true; auto-links: false;"> /** Custom NativeJdbcExtractor */ private NativeJdbcExtractor nativeJdbcExtractor;</pre> <p></p> 当我们想用驱动对象所提供的原始API的时候,可以通过JdbcTemplate的如下代码: <br /> <pre class="brush:java; toolbar: true; auto-links: false;"> public void setNativeJdbcExtractor(NativeJdbcExtractor extractor) { this.nativeJdbcExtractor = extractor; }</pre>这样将会获取真正的目标对象而不是代理对象。 <br /> <p>spring默认提供面向Commons DBCP、C3P0、Weblogic、Websphere等数据源的<span style="line-height:18px;font-family:'Courier New', Arial;white-space:pre;font-size:12px;">NativeJdbcExtractor的实现类: CommonsDbcpNativeJdbcExtractor:为Jakarta Commons DBCP数据库连接池所提供的NativeJdbcExtractor实现类 C3P0NativeJdbcExtractor:为C3P0数据库连接池所提供的NativeJdbcExtractor实现类 WebLogicNativeJdbcExtractor:为Weblogic所准备的NativeJdbcExtractor实现类</span></p> <p><span style="line-height:18px;font-family:'Courier New', Arial;white-space:pre;font-size:12px;">WebSphereNativeJdbcExtractor:为WebSphere所准备的NativeJdbcExtractor实现类</span></p> <p><span style="font-family:''Courier New', Arial';"><span style="line-height:18px;white-space:pre;font-size:12px;"><b>控制JdbcTemplate的行为</b> JdbcTemplate在使用Statement或者PreparedStatement等进行具体的数据操作之前,会调用如下的代码:</span></span></p> <pre class="brush:java; toolbar: true; auto-links: false;"> 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()); }</pre> <p>这样便可以设置Statement每次抓取的行数 等等。</p> <p><b>SQLException到DataAccessException的转译</b> 因为JdbcTemplate直接操作的是JDBC API,所以它需要捕获在此期间可能发生的SQLException,处理的宗旨是将SQLException 转译到spring的数据访问异常层次体系,以统一数据访问异常的处理方式,这个工作主要是交给了SQLExceptionTranslator,该 接口的定义如下:</p> <pre class="brush:java; toolbar: true; auto-links: false;">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> <p></p> 该接口有两个主要的实现类,SQLErrorCodeSQLExceptionTranslator和SQLStateSQLExceptionTranslator,如下所示: <img style="width:658px;height:193px;" alt="Spring JDBC最佳实践(2)" src="https://simg.open-open.com/show/276a4cefd578031e27ccc5baef8359fd.jpg" /> <p></p>