看JdbcTemplate的源码,我们看到
public JdbcTemplate(DataSource dataSource, boolean lazyInit) { setDataSource(dataSource); setLazyInit(lazyInit); afterPropertiesSet(); }JdbcTemplate类继承了JdbcAccessor,dataSource属性也是JdbcAccessor类的。在构造对象时传如数据源对象,数据源封装连接数据库的必须要素。 以JdbcTemplate的update()方法为例:
public int update(final String sql) throws DataAccessException { Assert.notNull(sql, "SQL must not be null"); if (logger.isDebugEnabled()) { logger.debug("Executing SQL update [" + sql + "]"); } class UpdateStatementCallback implements StatementCallback<Integer>, SqlProvider { @Override public Integer doInStatement(Statement stmt) throws SQLException { int rows = stmt.executeUpdate(sql); if (logger.isDebugEnabled()) { logger.debug("SQL update affected " + rows + " rows"); } return rows; } @Override public String getSql() { return sql; } } return execute(new UpdateStatementCallback()); }我们看到在这个方法里面,定义了一个类UpdateStatementCallback,它实现了StatementCallback和SqlProvider接口,这两个接口都只含有一个方法,分别是doInStatement(),和getSql(),其中StatementCallback方法中传入一个我们熟悉的Statement对象,用来执行sql语句。定义完这个类后,将这个类的一个实例传递给execute()方法。execute()如下:
@Override public <T> T execute(StatementCallback<T> action) throws DataAccessException { Assert.notNull(action, "Callback object must not be null"); Connection con = DataSourceUtils.getConnection(getDataSource()); Statement stmt = null; try { Connection conToUse = con; if (this.nativeJdbcExtractor != null && this.nativeJdbcExtractor.isNativeConnectionNecessaryForNativeStatements()) { conToUse = this.nativeJdbcExtractor.getNativeConnection(con); } stmt = conToUse.createStatement(); applyStatementSettings(stmt); Statement stmtToUse = stmt; if (this.nativeJdbcExtractor != null) { stmtToUse = this.nativeJdbcExtractor.getNativeStatement(stmt); } T result = action.doInStatement(stmtToUse); handleWarnings(stmt); 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. JdbcUtils.closeStatement(stmt); stmt = null; DataSourceUtils.releaseConnection(con, getDataSource()); con = null; throw getExceptionTranslator().translate("StatementCallback", getSql(action), ex); } finally { JdbcUtils.closeStatement(stmt); DataSourceUtils.releaseConnection(con, getDataSource()); } }这里面代码我们也容易看懂,首先通过DataSourceUtils获取一个Connection对象,我们在jdbc中也是这么做的。接下来的那两个if判断有点看不懂,看了api大概是用于从连接池的包装对象中提取本地JDBC对象的接口。因为用的连接池,所以先判断nativeJdbcExtractor对象是否为空,不为空的话直接从此对象中获取对象。接下来就是执行sql拉,action.doInStatement(stmtToUse); 上述就是JdbcTemplate类执行一个普通update方法的全过程,看完发现其实也很简单。我们自己也可以写出来。可能就是spring自己封装的连接池的那一块东西毕竟复杂些。有时间再去研究研究。