日期:2014-05-16 浏览次数:20710 次
用语句创建器更新数据库
第一个回调接口是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