JdbcTemplate的介绍
以前实现一个简单的数据库操作的步骤是这样的,获取连接—创建Statement或PreparedStatement—执行数据库操作—获取结果(ResultSet)—其他操作—处理异常—关闭ResultSet—关闭Statement或PreparedStatement—关闭连接,不可能每次都写重复的这样代码,所以Spring把这些步骤弄成一个模版,也就是JdbcTemplate,在Spring的封装下,配置数据源连接这样JDBC编程中重复的代码由Spring JDBC容器来处理,也就是在配置文件里配置就好了
JdbcTemplate 部分示例代码如下
public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
......
@Override
//使用回调方法
public <T> T execute(ConnectionCallback<T> action) throws DataAccessException {
Assert.notNull(action, "Callback object must not be null");
Connection con = DataSourceUtils.getConnection(getDataSource());
try {
Connection conToUse = con;
if (this.nativeJdbcExtractor != null) {
// Extract native JDBC Connection, castable to OracleConnection or the like.
conToUse = this.nativeJdbcExtractor.getNativeConnection(con);
}
else {
// 创建一个连接代码, also preparing returned Statements.
conToUse = createConnectionProxy(con);
}
return action.doInConnection(conToUse);
}
catch (SQLException ex) {
// 释放连接,避免连接池死锁
// in the case when the exception translator hasn't been initialized yet.
DataSourceUtils.releaseConnection(con, getDataSource());
con = null;
throw getExceptionTranslator().translate("ConnectionCallback", getSql(action), ex);
}
finally {
DataSourceUtils.releaseConnection(con, getDataSource());
}
}
@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);
}
//创建Statement
stmt = conToUse.createStatement();
applyStatementSettings(stmt);
Statement stmtToUse = stmt;
if (this.nativeJdbcExtractor != null) {
stmtToUse = this.nativeJdbcExtractor.getNativeStatement(stmt);
}
//初始化Statement
T result = action.doInStatement(stmtToUse);
handleWarnings(stmt);
return result;
}
catch (SQLException ex) {
// 释放连接
// 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());
}
}
@Override
//直接传入SQL语句执行
public void execute(final String sql) throws DataAccessException {
if (logger.isDebugEnabled()) {
logger.debug("Executing SQL statement [" + sql + "]");
}
class ExecuteStatementCallback implements StatementCallback<Object>, SqlProvider {
@Override
public Object doInStatement(Statement stmt) throws SQLException {
stmt.execute(sql);
return null;
}
@Override
//获取SQL
public String getSql() {
return sql;
}
}
//执行回调函数
execute(new ExecuteStatementCallback());
}
JdbcTemplate比TransactionTemplate好的一点就是除了可以使用回调方法,还有就是可以只要SQL语句传入,直接执行。
JdbcTemplate实现示例
(1)编写配置文件步骤
① 配置数据源Bean
② 配置事务管理Bean ,依赖注入数据源
③ 配置目标对象Bean ,依赖注入数据源和事务管理
<!-- 配置数据源 -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<!-- 使用SQL Server数据库的驱动 -->
<property name="driverClassName">
<value>com.microsoft.sqlserver.jdbc.SQLServerDriver</value>
</property>
<property name="url">
<value>jdbc:sqlserver://localhost:1433</value>
</property>
<property name="username">
<value>sa</value>
</property>
<property name="password">
<value>12345678</value>
</property>
</bean>
<!-- 设定事务管理,依赖注入dataSource -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
</bean>
<bean id="JdbcDAO" class="spring.transaction.JdbcDAO">
<!-- 依赖注入dataSource -->
<property name="dataSource">
<ref bean="dataSource"/>
</property>
<!-- 依赖注入transactionManager -->
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
</bean>
(2)使用JdbcTemplate,和事务处理结合在一起
public class JdbcDAO {
private DataSource dataSource;
private PlatformTransactionManager transactionManager;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public void setTransactionManager(
PlatformTransactionManager transactionManager) {
this.transactionManager = transactionManager;
}
// 使用JdbcTemplate
public void create(String msg) {
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
TransactionStatus status = transactionManager.getTransaction(def);
try {
//通过jdbcTemplate 的构造方法将dataSource注入
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
jdbcTemplate.update("INSERT INTO student VALUES('张三','男',18)");
} catch (DataAccessException e) {
// 执行status.setRollbackOnly()
status.setRollbackOnly();
throw e;
} finally {
transactionManager.commit(status);
}
}
}
(3)把JdbcTemplate 依赖于dataSource配置在配置文档
也可以把JdbcTemplate 依赖于dataSource配置在配置文档,JdbcDAO类就省略掉JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
在配置文文档增加jdbcTemplate的Bean,然后将dataSource依赖注入,然后在DAO的Bean直接依赖注入jdbcTemplate,不用依赖注入dataSource了
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
</bean>
<bean id="JdbcDAO" class="spring.transaction.JdbcDAO">
<!-- 依赖注入jdbcTemplate-->
<property name="jdbcTemplate">
<ref bean="jdbcTemplate"/>
</property>
<!-- 依赖注入transactionManager -->
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
</bean>
注意:因为将jdbcTemplate依赖注入JdbcDAO类中,所以还要在类增加jdbcTemplate的定义及setJdbcTemplate()方法
(4)还可以将SQL语句通过IoC注入到JdbcDAO类中
<bean id="JdbcDAO" class="spring.transaction.JdbcDAO">
.....
<property name="sql">
<value>INSERT INTO student VALUES('张三','男',18)</value>
</property>
</bean>
* 然后同上,类增加sql的定义及setSql()方法*