为什么用Spring来进行事务控制?
Spring的事务管理器:
事务管理器实现 | 目标 |
org.springframework.jdbc.datasource.DataSourceTransactionMan | 在JDBC DataSource中管理事务 (须注入数据源datasource |
org.springframework.orm.hibernate.HibernateTransactionMana | 管理Hibernate事务 (须注入SessionFactory Bean参数) |
org.springframework.orm.jdo.JdoTransactionManager | 管理JDO事务 |
org.springframework.transaction.jta.JtaTransactionManager | 使用一个JTA管理事务,在一个事务跨越多个资源时必须使用 (无须注入参数) |
org.springframework.orm.ojb.PersistenceBrokerTransac | 管理Apache的OJB事务 |
1、JTA事务管理器无须注入参数,是因为全局事务的JTA资源由JAVA EE服务器提供,而Spring容器能自行从JAVA EE服务器中获取该事务资源,所以无须使用依赖注入来配置。
2、当使用JTA全局事务策略时,实际底层须应用服务器支持,而不同的应用服务器所提供的JTA全局事务可能存在细节上的差异,因此实际配置全局事务管理器是可能需要使用JtaTransactionManager的子类,如:OC4JtaTransactionManager(Oracle提供的应用服务器)、WebLogicJtaTransactionMa
二、Spring编程式事务示例
步骤一、编写spring配置文件
下面实例使用DataSourceTransactionMan
查看Spring的配置信息:(applicationContext.xml):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="propertyConfig"
class="org.springframework.beans.factory.config.
PropertyPlaceholderConfigurer">
<property name="location">
<value>connect.properties</value>
</property>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName">
<value>${db.driver}</value>
</property>
<property name="url">
<value>${db.url}</value>
</property>
<property name="username">
<value>${db.username}</value>
</property>
<property name="password">
<value>${db.password}</value>
</property>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource">
<ref bean="dataSource" />
</property>
</bean>
<!-- JDBC事务管理器 注意:事务管理器传的参数是数据源-->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.
DataSourceTransactionManager" scope="singleton">
<property name="dataSource">
<ref bean="dataSource" />
</property>
</bean>
<!-- 声明事务模板 -->
<bean id="transactionTemplate"
class="org.springframework.transaction.support.
TransactionTemplate">
<property name="transactionManager">
<ref bean="transactionManager" />
</property>
</bean>
<bean id="bankDao" class="com.sunflower.dao.BankDaoImp">
<property name="jdbcTemplate">
<ref bean="jdbcTemplate" />
</property>
<property name="transactionTemplate">
<ref bean="transactionTemplate" />
</property>
</bean>
</beans>
上 面代码中配置了一个org.springframework.transaction.support.TransactionTemplate实例,要 在代码中添加事务,Spring为我们提供了一种方法就是使用TransactionTemplate类。我们要为 TransactionTemplate装配一个TransactionManager,
<!-- Hibernate事务管理器
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.
HibernateTransactionManager" scope="singleton">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager" scope="singleton" >
</bean>
package com.sunflower.dao;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
import com.sunflower.entity.People;
public class BankDaoImp implements BankDao {
private JdbcTemplate jdbcTemplate;
private TransactionTemplate transactionTemplate;
public JdbcTemplate getJdbcTemplate() {
return jdbcTemplate;
}
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public TransactionTemplate getTransactionTemplate() {
return transactionTemplate;
}
public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
this.transactionTemplate = transactionTemplate;
}
@Override
public double getMoney(final People people) {
double money = people.getMoney();
// 开始事务,如果出现状况则回滚
transactionTemplate.execute(new TransactionCallback<People>() {
@Override
public People doInTransaction(TransactionStatus ts) {
try {
final People people2 = new People();
// 使用JdbcTemplate进行持久化层操作
String sql = "select money from bank where name = ?";
Object[] params = new Object[] { people.getName() };
// 查询
jdbcTemplate.query(sql, params, new RowCallbackHandler() {
@Override
public void processRow(ResultSet rs)
throws SQLException {
people2.setMoney(rs.getDouble("money"));
System.out.println(people.getName() + "用户还有"
+ rs.getDouble("money") + "元余款");
System.out.println(people.getName() + "要从账户中取出"
+ people.getMoney() + "元");
if (people2.getMoney() < people.getMoney()) {
System.out.println("余额不足");
people.setMoney(-1);
return;
}
}
});
if (people.getMoney() < 0)
return null;
else {
sql = "update bank set money = ? where name = ?";
Object[] params2 = new Object[] {
people2.getMoney() - people.getMoney(),
people.getName() };
jdbcTemplate.update(sql, params2);
System.out.println("剩余余额:"
+ (people2.getMoney() - people.getMoney()));
}
}
catch (Exception e) {
ts.setRollbackOnly();
}
// 如果成功,事务被提交
return people;
}
});
return people.getMoney();
}
}
调 用TransactionTemplate实例的execute()方法将执行包含在TransactionCallback实例里的代码。如果代码出现 异常,调用TransactionStatus对象的setRollbackOnly()将事务回滚。否则,如果doInTransaction()方法 正常返回,事务将被提交。