日期:2014-05-16 浏览次数:20603 次
用语句创建器更新数据库
第一个回调接口是PerparedStatementCreator,实现这个接口来覆盖整个更新过程的语句创建任务。我们先看下源代码中的PerparedStatementCreator接口,然后实现我们自己的接
口。
?
public interface PreparedStatementCreator { /** * Create a statement in this connection. Allows implementations to use * PreparedStatements. The JdbcTemplate will close the created statement. * @param con Connection to use to create statement * @return a prepared statement * @throws SQLException there is no need to catch SQLExceptions * that may be thrown in the implementation of this method. * The JdbcTemplate class will handle them. */ PreparedStatement createPreparedStatement(Connection con) throws SQLException; }
?
源代码中只定义了一个方法createPreparedStatement,在connection连接的基础上创建statement,使我们可以使用PreparedStatements实例,创建完,jdbcTemplate会自动关闭
Connection连接,下面我们实现这个接口。
public class InsertPreparedStatementCreator implements PreparedStatementCreator{ private User user; public InsertPreparedStatementCreator(User user){ this.user = user; } public PreparedStatement createPreparedStatement(Connection conn)throws Exception{ String sql = "insert into user value(?,?); PreparedStatement ps = conn.prepareStatement(sql); ps.setString(user.getUsername()); ps.setString(user.getPassword()); return ps; } }
?
我们实现后,只需要创建PreparedStatement ,并且把参数绑定上去,然后返回,在处理过程中不需要进行异常处理,因为方法签名中已经给我们抛出了异常,也不用关闭数据库
连接或者打开数据库连接,这些spring都给我们做好了,然后调用jdbcTemplate中的update方法即可。
jdbcTemplate.update(new InsertPreparedStatementCreator(user));
当然也可以用另一种方式。
?
jdbcTemplate.update(new PreparedStatementCreator(){ String sql = "insert into user value(?,?); PreparedStatement ps = conn.prepareStatement(sql); ps.setString(user.getUsername()); ps.setString(user.getPassword()); return ps; });
?
这里其实是个回调函数,在设计模式中是模板方法模式。
模板方法使用继承机制实现。在父类中定义不变的,然后把变化的定义成一个抽象方法,供子类实现。因此模板方法的 父类一般也是一个抽象类。
在jdbcTemplate中的执行:
我们的update方法调用了jdbcTemplate方法中的
?
public int update(PreparedStatementCreator psc) throws DataAccessException { return update(psc, (PreparedStatementSetter) null); }
?
接着调用
protected int update(final PreparedStatementCreator psc, final PreparedStatementSetter pss) throws DataAccessException { if (logger.isDebugEnabled()) { String sql = getSql(psc); logger.debug("Executing SQL update" + (sql != null ? " [" + sql + "]" : "")); } Integer result = (Integer) execute(psc, new PreparedStatementCallback() { public Object doInPreparedStatement(PreparedStatement ps) throws SQLException { try { if (pss != null) { pss.setValues(ps); } int rows = ps.executeUpdate(); if (logger.isDebugEnabled()) { logger.debug("SQL update affected " + rows + " rows"); } return new Integer(rows); } finally { if (pss instanceof ParameterDisposer) { ((ParameterDisposer) pss).cleanupParameters(); } } } }); return result.intValue(); }
?
?
方法的关键:
int rows = ps.executeUpdate();
return new Integer(rows);
执行了preparedStatement.executeUpdate().然后返回执行后的值,和我们自己写是一样。在这里还是没有看到spring是如何打开数据库连接的。继续看,注意到一个方法的调用
Integer result = (Integer) execute(psc, new PreparedStatementCallback() 。。。。。。
我们找到这个方法
?
public Object execute(PreparedStatementCreator psc, PreparedStatementCallback action) throws DataAccessException { Assert.notNull(psc, "PreparedStatementCreator must not be null"); Assert.notNull(action, "Callback object must not be null"); Connection con = DataSourceUtils.getConnection(getDataSource()); PreparedStatement ps = null; try { Connection conToUse = con; if (this.nativeJdbcExtractor != null && this.nativeJdbcExtractor.isNati