先通过一个小例子,简单使用一下。
配置文件 applicationContext.xml
<beans default-autowire ="autodetect"> <bean id ="dataSource" class ="org.apache.commons.dbcp.BasicDataSource"> <property name ="driverClassName"> <value>oracle.jdbc.driver.OracleDriver</value> </property> <property name ="url"> <value>jdbc:oracle:thin:@localhost:1521:orcl</value> </property> <property name="username"> <value>username</value> </property> <property name="password"> <value>password</value> </property> <property name="maxActive"> <value>10</value> </property> <property name="maxIdle"> <value>2</value> </property> </bean> <bean id ="JdbcTemplate" class ="org.springframework.jdbc.core.JdbcTemplate"> <property name ="dataSource"> <ref bean ="dataSource" /> </property> </bean> </beans>
程序
public static void main(String[] args) { ClassPathResource res = new ClassPathResource("applicationContext.xml"); XmlBeanFactory factory = new XmlBeanFactory(res); JdbcTemplate jdbcTemplate = (JdbcTemplate) factory .getBean("JdbcTemplate"); jdbcTemplate .update("delete from TB_USER where ID= 466 "); }
只需要一句代码, 就完成了我们关心的 jdbc 操作。
F3,看下 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, SqlProvider {
public Object doInStatement(Statement stmt) throws SQLException {
int rows = stmt.executeUpdate(sql);
if (logger.isDebugEnabled()) {
logger.debug("SQL update affected " + rows + " rows");
}
return new Integer(rows);
}
public String getSql() {
return sql;
}
}
return ((Integer) execute(new UpdateStatementCallback())).intValue();
}
public Object execute(StatementCallback 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);
}
Object result = action.doInStatement(stmtToUse);
handleWarnings(stmt.getWarnings());
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());
}
}
这里就用到了 Template 设计模式,估计Spring 的这个模块叫 JdbcTemplate 的原因也在于此。
action.doInStatement(stmtToUse);
执行主体逻辑,
至于 之后的 catch,finally 等,都是无聊又必须有的 开闭Connection 之类的操作,
Spring 把他们固定成模板代码,都不用动他们了,
只需实现Spring 留给我们的一句 : action.doInStatement(stmtToUse) 。
Spring 是使用 Java 回调 实现的。
update 方法里, 初始化了一个类, UpdateStatementCallback ,
UpdateStatementCallback 里,doInStatement 方法里,就是要执行的主体代码,
但 update 方法并没有直接调用doInStatement ,
而是把 整个UpdateStatementCallback 作为参数,传给了 execute 方法,
再由 execute 调用 UpdateStatementCallback 的 doInStatement ,
很绕,总结一下就是,A 里边有个B,A委托C调用自己的B,
那为什么A自己不调呢,上边的例子就是一个原因,
A 是我们负责写的类,C 是Spring,
因为 调用B 之前和之后 要做额外操作, 是很烦的工作,所以A就把活推给C了。