模板模式在Spring 中的应用

来源:互联网 发布:软件版权摊销年限 编辑:程序博客网 时间:2024/04/30 08:50

在spring里面我们一般是这样来使用模板模式的:

JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
jdbcTemplate.update("UPDATE user SET age = 10 WHERE id = 'erica'");

或者:

JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
jdbcTemplate
.update(
"UPDATE user SET age = ? WHERE id = ?",
new PreparedStatementSetter() {
public void setValues(PreparedStatementSetter ps)
throws SQLException {
ps.setInt(1, 18);
ps.setString(2, "erica");
}
}
);

那么具体在spring里面他是怎么运作的呢?

下面以query查询为例:

public class JdbcTemplate extends JdbcAccessor implements JdbcOperations, InitializingBean {

。。。。。。。。。。。。。。。。。。。。。。。。。

protected Object query(
   PreparedStatementCreator psc, final PreparedStatementSetter pss, final ResultSetExtractor rse)
   throws DataAccessException {
  if (logger.isDebugEnabled()) {
   String sql = getSql(psc);
   logger.debug("Executing SQL query" + (sql != null ? " [" + sql  + "]" : ""));
  }
  return execute(psc, new PreparedStatementCallback() {

//此处以 PreparedStatementCallback 为参数调用 execute()方法,在execute()方法里面回调传入的方法。在回调方法里面即根据传入的 PreparedStatement 执行 查询操作,返回结果。而 PreparedStatement  的获取是在调用回调方法的客户端实现即在execute()方法里面获取,并作为参数传给回调方法。
   public Object doInPreparedStatement(PreparedStatement ps) throws SQLException {
    ResultSet rs = null;
    try {
     if (pss != null) {
      pss.setValues(ps);
     }
     if (getFetchSize() > 0) {
      ps.setFetchSize(getFetchSize());
     }
     rs = ps.executeQuery();
     ResultSet rsToUse = rs;
     if (nativeJdbcExtractor != null) {
      rsToUse = nativeJdbcExtractor.getNativeResultSet(rs);
     }
     return rse.extractData(rsToUse);
    }
    finally {
     JdbcUtils.closeResultSet(rs);
     if (pss instanceof ParameterDisposer) {
      ((ParameterDisposer) pss).cleanupParameters();
     }
    }
   }
  });
 }

那么在execue()方法里面是怎样回调的呢?下面看看execue()方法:

public Object execute(PreparedStatementCreator psc, PreparedStatementCallback action) {
  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);
   DataSourceUtils.applyTransactionTimeout(ps, getDataSource());
   PreparedStatement psToUse = ps;
   if (this.nativeJdbcExtractor != null) {
    psToUse = this.nativeJdbcExtractor.getNativePreparedStatement(ps);
   }
   Object result = action.doInPreparedStatement(psToUse);
   SQLWarning warning = ps.getWarnings();
   throwExceptionOnWarningIfNotIgnoringWarnings(warning);
   return result;
  }
  catch (SQLException ex) {
   throw getExceptionTranslator().translate(
     "executing PreparedStatementCallback [" + psc + "]", getSql(psc), ex);
  }
  finally {
   if (psc instanceof ParameterDisposer) {
    ((ParameterDisposer) psc).cleanupParameters();
   }
   JdbcUtils.closeStatement(ps);
   DataSourceUtils.closeConnectionIfNecessary(con, getDataSource());
  }
 }

添加删除的操作类似,只是他们的实现都在以execute命名的方法里面。

public void execute(final String sql) throws DataAccessException {
  if (logger.isDebugEnabled()) {
   logger.debug("Executing SQL statement [" + sql + "]");
  }
  class ExecuteStatementCallback implements StatementCallback, SqlProvider {
   public Object doInStatement(Statement stmt) throws SQLException {
    stmt.execute(sql);
    return null;
   }
   public String getSql() {
    return sql;
   }
  }
  execute(new ExecuteStatementCallback());
 }

public Object execute(final StatementCallback action) {
  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();
   DataSourceUtils.applyTransactionTimeout(stmt, getDataSource());
   Statement stmtToUse = stmt;
   if (this.nativeJdbcExtractor != null) {
    stmtToUse = this.nativeJdbcExtractor.getNativeStatement(stmt);
   }
   Object result = action.doInStatement(stmtToUse);
   SQLWarning warning = stmt.getWarnings();
   throwExceptionOnWarningIfNotIgnoringWarnings(warning);
   return result;
  }
  catch (SQLException ex) {
   throw getExceptionTranslator().translate("executing StatementCallback", getSql(action), ex);
  }
  finally {

//这里就是我们自己写程序的时候需要写的关于数据库链接的关闭操作
   JdbcUtils.closeStatement(stmt);
   DataSourceUtils.closeConnectionIfNecessary(con, getDataSource());
  }
 }