一、概述
(一)基本概念
1、什么是Spring事务处理?
Spring的事务处理,可以说是 Spring AOP 的一种实现。因为事务处理是所谓方面( Aspect )的一个子集。因此默认情况下,事务处理是利用 Java 动态代理机制实现的,这样就必须先定义一个接口,然后再编写实现;而对于没有接口的 Javabean ,则通过CGLIB 实现。这部分是 Spring AOP 部分的内容。
2 、两种事务处理方式
和 EJB 一样, Spring 也提供两种事务处理方式,一种是编程式事务处理;一种是声明式事务处理。
(二)框架图
实现事务处理的两种方式
1、Java 动态代理
2、CGLIB
两种事务处理方式
1、编程式事务处理
2、声明式事务处理
(三)何时使用什么
如果需要大量的事务处理,就用声明式事务处理,如果很少的事务处理,就用编程式
二、详细
编程式事务处理与声明式事务处理
(一)编程式事务处理
1 、使用TransactionTemplate进行事务处理(Spring进行commit和rollback)
( 1 )使用事务处理的类
import javax.sql.DataSource;
import org.springframework.jdbc.core.*;
import org.springframework.transaction.*;
import org.springframework.dao.*;
public class bookDAO {
private DataSource dataSource; // 依赖注入 dataSource ,管理数据库
private PlatformTransationManager transactionManager; // 依赖注入管理事务
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public void setTransactionManager(PlatformTransationManager transactionManager) {
this.transactionManager = transactionManager;
}
public int create(String msg){
TransactionTemplate transactionTemplate=new TransactionTemplate(transactionManager);
// 调用 transactionTemplate 的 execute 方法进行事务管理
Object result= transactionTemplate.execute (
// 这是一个回调函数,实现了 TransactionCallback 接口的 doInTransaction 方法,就是在这个方法里写数据库新增数据的操作
new TransactionCallback(){
public Object doInTransaction(TransactionStatus status){
// 数据库操作代码
return resultObject;
}
}
)
}
}
如果不想返回结果( resultObject ),则可以用 TransactionCallbackWithoutResult 来实现 TransactionCallback 接口,代码如下:
new TransactionCallback WithoutResult (){
public Object doInTransaction WithoutResult (TransactionStatus status){
// 数据库操作代码
}
}
( 2 )配置文件
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <!-- 设定dataSource --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <!-- 使用SQL Server 数据库 --> <property name="driverClassName"> <value>com.microsoft.jdbc.sqlserver.SQLServerDriver</value> </property> <property name="url"> <value>jdbc:Microsoft:sqlserver://localhost:1433/stdb</value> </property> <property name="name"> <value>admin</value> </property> <property name="msg"> <value>admin</value> </property> </bean> <!-- 设定transactionManager --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource"> <ref bean="dataSource" /> </property> </bean> <!-- 示例中 DAO --> <bean id="bookDAO" class="com.bookDAO"> <property name="dataSource"> <ref bean="dataSource" /> </property> <property name="transactionManager"> <ref bean="transactionManager"> </property> </bean> </beans>
这样 Spring 就可以自动进行 commit 和 rollback 这两个操作了。粉色部分是为了和 bookDAO 中的粉色部分相匹配。
2 、使用JdbcTemplate进行事务处理(硬编码进行commit和rollback)
( 1 )使用事务处理的类
import javax.sql.DataSource;
import org.springframework.jdbc.core.*;
import org.springframework.transaction.*;
import org.springframework.dao.*;
public class bookDAO {
private DataSource dataSource; // 依赖注入 dataSource ,管理数据库
private PlatformTransationManager transactionManager; // 依赖注入管理事务
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public void setTransactionManager(PlatformTransationManager transactionManager) {
this.transactionManager = transactionManager;
}
public int create(String msg){
/* TransactionTemplate transactionTemplate=new TransactionTemplate(transactionManager);
Object result= transactionTemplate.execute (
new TransactionCallback()
{
public Object doInTransaction(TransactionStatus status)
{
return resultObject;
}
}
)*/
// 使用下面的代码替换上面注释掉的部分
DefaultTransactionDefinition def =new DefaultTransactionDefinition();
TransactionStatus status=transactionManager.getTransaction(def);
try
{
JdbcTemplate jdbcTemplate=new JdbcTemplate(dataSource);
jdbcTemplate.update(“INSERT INTO book VALUES(1,’gf’,’Mastering Spring’)”);
}
catch(DataAccessException ex)
{
transactionzManager.rollback(status);
throw ex;
}
finally
{
transactionManager.commit(status);
}
}
}
( 2 )配置文件
同上
( 二)声明式事务处理
1、
( 1 )使用事务处理的类
import javax.sql.DataSource;
import org.springframework.jdbc.core.*;
import org.springframework.transaction.*;
import org.springframework.dao.*;
public class bookDAO {
private DataSource dataSource; // 依赖注入 dataSource ,管理数据库
private PlatformTransationManager transactionManager; // 依赖注入管理事务
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public void setTransactionManager(PlatformTransationManager transactionManager) {
this.transactionManager = transactionManager;
}
public int create(String msg){
① /* TransactionTemplate transactionTemplate=new TransactionTemplate(transactionManager);
Object result= transactionTemplate.execute (
new TransactionCallback()
{
public Object doInTransaction(TransactionStatus status)
{
return resultObject;
}
}
)*/
② /* DefaultTransactionDefinition def=new DefaultTransactionDefinition();
TransactionStatus status=transactionManager.getTransaction(def);
try
{
JdbcTemplate jdbcTemplate=new JdbcTemplate(dataSource);
jdbcTemplate.update(“INSERT INTO book VALUES(1,’gf’,’Mastering Spring’)”);
}
catch(DataAccessException ex)
{
transactionzManager.rollback(status);
throw ex;
}
finally
{
transactionManager.commit(status);
} */
// 使用下面的代码替换上面注释掉的部分
JdbcTemplate jdbcTemplate=new JdbcTemplate(dataSource);
jdbcTemplate.update(“INSERT INFO book VALUES(1,’gf’,’Mastering Spring’)”);
/ / 与 ② 相比,此段代码省去了 commit 和 rollback 事务处理语句;与 ① 相比,不必实现 TransactionCallback 接口
}
}
( 2 )配置文件
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <!-- 设定dataSource --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <!-- 使用SQL Server 数据库 --> <property name="driverClassName"> <value>com.microsoft.jdbc.sqlserver.SQLServerDriver</value> </property> <property name="url"> <value>jdbc:Microsoft:sqlserver://localhost:1433/stdb</value> </property> <property name="name"> <value>admin</value> </property> <property name="msg"> <value>admin</value> </property> </bean> <!-- 设定 transactionManager --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource"> <ref bean="dataSource" /> </property> </bean> <!-- 示例中 DAO--> <bean id="bookDAO" class="com.bookDAO"> <property name="dataSource"> <ref bean="dataSource" /> </property> <!-- 与编程式事务处理相比,在 DAO 设置中去掉了这个属性,把它放到了代理类中。 --> <!-- <property name="transactionManager"> <ref bean="transactionManager"> </property> --> </bean> <!-- 声明式事务处理 --> <bean id="bookDAOProxy" class="org.springframework.transaction.interceptor.Transation.ProxyFactoryBean"> <property name="transacionManager"> <ref bean="transacionMaganer" /> </property> <property name="target"> <ref bean="bookDAO" /> </property> <property name="transactionAttributes"> <props> <!-- 表示对 bookDAO 中的 create 方法进行事务处理,并指明当前没有事务就新建一个(用PROPAGATION_REQUIRED 常量来表示的) --> <prop key="create * ">PROPAGATION_REQUIRED</prop> </props> </property> </bean> </beans>
2、
在applicationContext.xml中配置
<?xml version="1.0" encoding="gbk"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName"
value="com.microsoft.sqlserver.jdbc.SQLServerDriver">
</property>
<property name="url"
value="jdbc:sqlserver://localhost:1500;databaseName=ssh">
</property>
<property name="username" value="sa"></property>
<property name="password" value="sa"></property>
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.SQLServerDialect
</prop>
</props>
</property>
<property name="mappingResources">
<list>
<value>bank/entity/Account.hbm.xml</value>
</list>
</property>
</bean>
<bean id="AccountDAO" class="bank.dao.AccountDAO">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
<bean id="AccountManager" class="bank.biz.AccountManager">
<property name="dao">
<ref bean="AccountDAO" />
</property>
</bean>
<bean name="/account" class="bank.action.AccountAction">
<property name="accountManager">
<ref bean="AccountManager" />
</property>
</bean>
<!--通用事务管理器-->
<bean id="TransactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!--指定事务策略,声明一个通知,用以指出要管理哪些事务方法及如何管理-->
<tx:advice id="txAdvice" transaction-manager="TransactionManager">
<tx:attributes>
<!-- 对get/load/search开头的方法要求只读事务 -->
<tx:method name="find*" propagation="SUPPORTS"
read-only="true" />
<!-- 对其它方法要求事务 -->
<tx:method name="*" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>
<!--声明一个config,用以将事务策略和业务类关联起来-->
<aop:config>
<!-- 添加事务支持,因为前面配置的transactionManager是专对Hibernate的事务管理器-->
<aop:pointcut id="bizMethods" expression="execution(* bank.biz..*.*(..))" />
<!-- 织入 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="bizMethods" />
</aop:config>
</beans>