Spring事务
一、Spring事务接口
spring事务提供了三个主要的接口PlatformTransactionManager、TransactionDefination定义事务隔离级别、TransactionDefination定义事务传播行为、TransactionStatus接口。
PlatformTransactionManager:事务管理器。
TransactionDefination:定义事务隔离级别:READ_UNCOMMITED、READ_COMMITTED、REPEATABLE_READ、SERIALIZABLE。mysql数据库默认的是REPEATABLE_READ级别4.
TransactionDefination:定义事务传播行为:PROPAGATION_REQUIRED、PROPAGATION_SUPPORTS、PROPAGATION_MANDATORY、PROPAGATION_REQUIRES_REW、PROPAGATION_NOT_SUPPORTED、PROPAGATION_NEVER、PROPAGATION_NESTED等
二、spring事务管理--转账案例
2.1、环境搭建
引入相关jar包、jdbc.properties、log4j.properties等
AccountService接口、AccountServiceImpl实现类
AccountDao接口、AccountDaoImpl实现类
AccountService.java接口
1: package com.spring.demo1;
2:3: public interface AccountService {4: public void transfer(String OutName,String InName,Double money);5: }6:AccountDao.java接口:
1: package com.spring.demo1;
2: public interface AccountDao {3: public void outMoney(String OutName,Double money);4: public void inMoney(String InName,Double money);5: }6:AccountDaoImpl.java
1: package com.spring.demo1;
2:3: import org.springframework.jdbc.core.support.JdbcDaoSupport;
4: public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {5:6: public void inMoney(String InName, Double money) {7: // TODO Auto-generated method stub
8: String sql="update account set money=money + ? where name= ?";
9: this.getJdbcTemplate().update(sql,money,InName);
10: }11:12: public void outMoney(String OutName, Double money) {13: // TODO Auto-generated method stub
14: String sql="update account set money=money - ? where name= ?";
15: this.getJdbcTemplate().update(sql,money,OutName);
16: }17:18: }19:
2.2、编程式事务管理
ApplicationContex.xml
1: <?xml version="1.0" encoding="UTF-8" ?>2: <beans xmlns="http://www.springframework.org/schema/beans"
3: xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"4: xmlns:context="http://www.springframework.org/schema/context"
5: xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"6: xsi:schemaLocation="http://www.springframework.org/schema/beans
7: http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
8: http://www.springframework.org/schema/context
9: http://www.springframework.org/schema/context/spring-context-3.0.xsd
10: http://www.springframework.org/schema/tx
11: http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
12: http://www.springframework.org/schema/aop
13: http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
14:15:16: <!-- 引入外部的属性文件 -->17: <context:property-placeholder location="classpath:jdbc.properties" />
18:19: <!-- 配置c3p0连接池20: <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"21: p:driverClass="${jdbc.driverClass}"
22: p:jdbcUrl="${jdbc.url}"
23: p:user="${jdbc.username}"
24: p:password="${jdbc.password}" />-->
25:26: <!-- 配置dbcp连接池 -->27: <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"28: destroy-method="close"
29: p:driverClassName="${jdbc.driverClass}"
30: p:url="${jdbc.url}"
31: p:username="${jdbc.username}"
32: p:password="${jdbc.password}" />
33:34: <!-- 配置Jdbc模板 -->35: <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"36: p:dataSource-ref="dataSource" />
37:38: <!-- 业务层 -->39: <bean id="accountService" class="com.spring.demo4.AccountServiceImpl" p:accountDao-ref="accountDao"/>40:41: <!-- Dao类 -->42: <bean id="accountDao" class="com.spring.demo4.AccountDaoImpl" p:dataSource-ref="dataSource" />43:44: <!-- 配置事务管理器 -->45: <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"46: p:dataSource-ref="dataSource" />
47:48: <!-- 定义一个事务管理模板 :spring为了简化事务管理的代码而提供的类-->49: <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"50: p:transactionManager-ref="transactionManager" />
51:52: </beans>53:AccountServiceImpl.java
1: package com.spring.demo1;
2:3: import org.springframework.transaction.TransactionStatus;
4: import org.springframework.transaction.support.TransactionCallback;
5: import org.springframework.transaction.support.TransactionCallbackWithoutResult;
6: import org.springframework.transaction.support.TransactionTemplate;
7: import com.sun.istack.internal.FinalArrayList;
8: public class AccountServiceImpl implements AccountService {9:10: //注入转账的DAO类
11:12: private AccountDao accountDao;
13: public void setAccountDao(AccountDao accountDao) {14: this.accountDao = accountDao;
15: }16:17: //注入事务管理的模板
18: private TransactionTemplate transactionTemplate;
19: public void setTransactionTemplate(TransactionTemplate transactionTemplate) {20: this.transactionTemplate = transactionTemplate;
21: }22:23: public AccountDao getAccountDao() {
24: return accountDao;
25: }26:27: public TransactionTemplate getTransactionTemplate() {
28: return transactionTemplate;
29: }30:31: public void transfer(final String OutName,final String InName,final Double money) {32: // TODO Auto-generated method stub
33: transactionTemplate.execute(new TransactionCallbackWithoutResult() {
34: @Override35: protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {36: // TODO Auto-generated method stub
37: accountDao.outMoney(OutName, money);38: accountDao.inMoney(InName, money);39: }40: });41:42: }43:44: }45:测试类:springtestdemo1.java
1: package com.spring.demo1;2:3: import javax.annotation.Resource;4: import org.junit.Test;5: import org.junit.runner.RunWith;6: import org.springframework.test.context.ContextConfiguration;7: import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;8: @RunWith(SpringJUnit4ClassRunner.class)
9: @ContextConfiguration("classpath:applicationContext.xml")
10: public class springtestdemo1 {11: //测试业务层类:12: @Resource(name="accountService")
13: private AccountService accountService;
14: @Test15: public void demo1(){
16: accountService.transfer("aaa", "bbb", 200d);17: }18: }19:运行结果:
当修改一下AccountServiceImpl.java的代码
1: accountDao.outMoney(OutName, money);2: int i=1 / 0;3: accountDao.inMoney(InName, money);当不引入事务管理的运行结果: 发现用户aaa已经少了300块,但是用户bbb却没有增加.
当引入事务管理的运行结果: 这时候,用户aaa和bbb不会出现不一致的情况
2.3、声明式事务管理方式一:TransactionProxyFactoryBean
ApplicationContext2.xml
1: <?xml version="1.0" encoding="UTF-8" ?>2: <beans xmlns="http://www.springframework.org/schema/beans"
3: xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"4: xmlns:context="http://www.springframework.org/schema/context"
5: xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"6: xsi:schemaLocation="http://www.springframework.org/schema/beans
7: http://www.springframework.org/schema/beans/spring-beans-3.0.xsd8: http://www.springframework.org/schema/context9: http://www.springframework.org/schema/context/spring-context-3.0.xsd10: http://www.springframework.org/schema/tx11: http://www.springframework.org/schema/tx/spring-tx-3.0.xsd12: http://www.springframework.org/schema/aop13: http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
14:15: <!-- 引入外部的属性文件 -->16: <context:property-placeholder location="classpath:jdbc.properties" />17:18: <!-- 配置c3p0连接池19: <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"20: p:driverClass="${jdbc.driverClass}"
21: p:jdbcUrl="${jdbc.url}"
22: p:user="${jdbc.username}"
23: p:password="${jdbc.password}" />-->
24:25: <!-- 配置dbcp连接池 -->26: <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"27: destroy-method="close"
28: p:driverClassName="${jdbc.driverClass}"
29: p:url="${jdbc.url}"
30: p:username="${jdbc.username}"
31: p:password="${jdbc.password}" />
32:33: <!-- 配置Jdbc模板 -->34: <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"35: p:dataSource-ref="dataSource" />
36:37: <!-- 业务层 -->38: <bean id="accountService" class="com.spring.demo4.AccountServiceImpl" p:accountDao-ref="accountDao"/>39:40: <!-- Dao类 -->41: <bean id="accountDao" class="com.spring.demo4.AccountDaoImpl" p:dataSource-ref="dataSource" />42:43: <!-- 配置事务管理器 -->44: <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"45: p:dataSource-ref="dataSource" />
46:47: <!-- 配置业务层的代理 -->48: <!-- prop的格式:49: PROPAGATION:事务的传播行为50: ISOLATION : 事务的隔离级别51: readOnly: 只读
52: -Exception :发生哪些异常,回滚事务53: +Exception:发生哪些异常,事务不回滚54: -->55: <bean id="accountServiceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">56: <!-- 配置目标对象 -->57: <property name="target" ref="accountService" />58: <!-- 事务事务管理器 -->59: <property name="transactionManager" ref="transactionManager" />60: <!-- 注入事务的一些属性 -->61: <property name="transactionAttributes" >62: <props>63: <prop key="transfer">PROPAGATION_REQUIRED,+java.lang.ArithmeticException</prop>
64: </props>65: </property>
66: </bean>67: </beans>AccountServiceImpl.java
1: package com.spring.demo2;2: import org.springframework.transaction.TransactionStatus;3: import org.springframework.transaction.support.TransactionCallback;4: import org.springframework.transaction.support.TransactionCallbackWithoutResult;5: import org.springframework.transaction.support.TransactionTemplate;6: import com.sun.istack.internal.FinalArrayList;7: public class AccountServiceImpl implements AccountService {8: //注入转账的DAO类9: private AccountDao accountDao;
10: public void setAccountDao(AccountDao accountDao) {
11: this.accountDao = accountDao;12: }13: public void transfer(String OutName, String InName, Double money) {14: // TODO Auto-generated method stub15: accountDao.outMoney(OutName, money);16: int i=1/0;17: accountDao.inMoney(InName, money);18: }19: }20:测试类:springtestdemo2.java
1: package com.spring.demo2;2: import javax.annotation.Resource;3: import org.junit.Test;4: import org.junit.runner.RunWith;5: import org.springframework.test.context.ContextConfiguration;6: import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;7: /**
8: * 声明式9: *10: * @author su11: *12: */13: @RunWith(SpringJUnit4ClassRunner.class)
14: @ContextConfiguration("classpath:applicationContext2.xml")
15: public class springtestdemo2 {16: //测试业务层类:17: /**
18: *19: * 注入代理类:因为代理类已经增强了20: */21: //@Resource(name="accountService")
22: @Resource(name="accountServiceProxy")
23: private AccountService accountService;
24: @Test25: public void test(){
26: accountService.transfer("aaa", "bbb", 300d);27: }28: }运行结果图上。
2.4、声明式事务管理方式二:基于AspectJ的xml配置
ApplicationContex3.xml
1: <?xml version="1.0" encoding="UTF-8" ?>2: <beans xmlns="http://www.springframework.org/schema/beans"
3: xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"4: xmlns:context="http://www.springframework.org/schema/context"
5: xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"6: xsi:schemaLocation="http://www.springframework.org/schema/beans
7: http://www.springframework.org/schema/beans/spring-beans-3.0.xsd8: http://www.springframework.org/schema/context9: http://www.springframework.org/schema/context/spring-context-3.0.xsd10: http://www.springframework.org/schema/tx11: http://www.springframework.org/schema/tx/spring-tx-3.0.xsd12: http://www.springframework.org/schema/aop13: http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
14:15: <!-- 引入外部的属性文件 -->16: <context:property-placeholder location="classpath:jdbc.properties" />17:18: <!-- 配置c3p0连接池19: <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"20: p:driverClass="${jdbc.driverClass}"
21: p:jdbcUrl="${jdbc.url}"
22: p:user="${jdbc.username}"
23: p:password="${jdbc.password}" />-->
24:25: <!-- 配置dbcp连接池 -->26: <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"27: destroy-method="close"
28: p:driverClassName="${jdbc.driverClass}"
29: p:url="${jdbc.url}"
30: p:username="${jdbc.username}"
31: p:password="${jdbc.password}" />
32:33: <!-- 配置Jdbc模板 -->34: <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"35: p:dataSource-ref="dataSource" />
36:37: <!-- 业务层 -->38: <bean id="accountService" class="com.spring.demo4.AccountServiceImpl" p:accountDao-ref="accountDao"/>39:40: <!-- Dao类 -->41: <bean id="accountDao" class="com.spring.demo4.AccountDaoImpl" p:dataSource-ref="dataSource" />42:43: <!-- 配置事务管理器 -->44: <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"45: p:dataSource-ref="dataSource" />
46:47: <!-- 配置事务的通知:(事务的增强增强) -->48: <tx:advice id="txAdvice" transaction-manager="transactionManager">49: <tx:attributes>50: <!-- propagation:事务的传播行为51: isolation: 事务的隔离级别52: read-only:只读53: rollback-for:发生哪些异常回滚
54: no-rollback-for:发生哪些异常不回滚
55: -->56: <tx:method name="transfer" propagation="REQUIRED"/>57: </tx:attributes>58: </tx:advice>59:60: <!-- 配置切面 -->61: <aop:config>62: <!-- 配置切入点 -->63: <aop:pointcut expression="execution(* com.spring.demo3.AccountService+.*(..))" id="pointcut1" />64: <!-- 配置切面 -->65: <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1" />66: </aop:config>67: </beans>AccountServiceImpl.java
1: package com.spring.demo3;2: import org.springframework.transaction.TransactionStatus;3: import org.springframework.transaction.annotation.Transactional;4: import org.springframework.transaction.support.TransactionCallback;5: import org.springframework.transaction.support.TransactionCallbackWithoutResult;6: import org.springframework.transaction.support.TransactionTemplate;7: import com.sun.istack.internal.FinalArrayList;8: public class AccountServiceImpl implements AccountService {9: //注入转账的DAO类10: private AccountDao accountDao;
11: public void setAccountDao(AccountDao accountDao) {
12: this.accountDao = accountDao;13: }14: public void transfer(String OutName, String InName, Double money) {15: // TODO Auto-generated method stub16: accountDao.outMoney(OutName, money);17: // int i=1/0;18: accountDao.inMoney(InName, money);19: }20: }测试类:springtestdemo3.java
1: package com.spring.demo3;2:3: import javax.annotation.Resource;4: import org.junit.Test;5: import org.junit.runner.RunWith;6: import org.springframework.test.context.ContextConfiguration;7: import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;8: /**
9: * 声明式:基于AspectJ的XML的配置10: *11: * @author su12: *13: */14: @RunWith(SpringJUnit4ClassRunner.class)
15: @ContextConfiguration("classpath:applicationContext3.xml")
16: public class springtestdemo3 {17: //测试业务层类:18: @Resource(name="accountService")
19: private AccountService accountService;
20: @Test21: public void test(){
22: accountService.transfer("aaa", "bbb", 300d);23: }24: }
2.5、声明式事务管理方式三:基于@Transactional注解
ApplicationContext4.xml
1: <?xml version="1.0" encoding="UTF-8" ?>2: <beans xmlns="http://www.springframework.org/schema/beans"
3: xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"4: xmlns:context="http://www.springframework.org/schema/context"
5: xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"6: xsi:schemaLocation="http://www.springframework.org/schema/beans
7: http://www.springframework.org/schema/beans/spring-beans-3.0.xsd8: http://www.springframework.org/schema/context9: http://www.springframework.org/schema/context/spring-context-3.0.xsd10: http://www.springframework.org/schema/tx11: http://www.springframework.org/schema/tx/spring-tx-3.0.xsd12: http://www.springframework.org/schema/aop13: http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
14:15: <!-- 引入外部的属性文件 -->16: <context:property-placeholder location="classpath:jdbc.properties" />17:18: <!-- 配置c3p0连接池19: <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"20: p:driverClass="${jdbc.driverClass}"
21: p:jdbcUrl="${jdbc.url}"
22: p:user="${jdbc.username}"
23: p:password="${jdbc.password}" />-->
24:25: <!-- 配置dbcp连接池 -->26: <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"27: destroy-method="close"
28: p:driverClassName="${jdbc.driverClass}"
29: p:url="${jdbc.url}"
30: p:username="${jdbc.username}"
31: p:password="${jdbc.password}" />
32:33: <!-- 配置Jdbc模板 -->34: <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"35: p:dataSource-ref="dataSource" />
36:37: <!-- 业务层 -->38: <bean id="accountService" class="com.spring.demo4.AccountServiceImpl" p:accountDao-ref="accountDao"/>39:40: <!-- Dao类 -->41: <bean id="accountDao" class="com.spring.demo4.AccountDaoImpl" p:dataSource-ref="dataSource" />42:43: <!-- 配置事务管理器 -->44: <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"45: p:dataSource-ref="dataSource" />
46:47: <!-- 开启注解事务 -->48: <tx:annotation-driven transaction-manager="transactionManager"/>
49: </beans>AccountServiceImpl.java
1: package com.spring.demo4;2: import org.springframework.transaction.TransactionStatus;3: import org.springframework.transaction.annotation.Isolation;4: import org.springframework.transaction.annotation.Propagation;5: import org.springframework.transaction.annotation.Transactional;6: import org.springframework.transaction.support.TransactionCallback;7: import org.springframework.transaction.support.TransactionCallbackWithoutResult;8: import org.springframework.transaction.support.TransactionTemplate;9: import com.sun.istack.internal.FinalArrayList;10: /**
11: * @Transactional:注解中的属性12: * propagation:事务的传播行为13: * isolation: 事务的隔离级别14: * readOnly:只读15: * rollbackFor:发生哪些异常回滚16: * noRollbackFor:发生哪些异常不回滚17: *18: * @author su19: *20: */21: @Transactional(propagation=Propagation.REQUIRED,isolation=Isolation.DEFAULT,readOnly=false)22: public class AccountServiceImpl implements AccountService {23:24: //注入转账的DAO类25:26: private AccountDao accountDao;
27: public void setAccountDao(AccountDao accountDao) {
28: this.accountDao = accountDao;29: }30:31: public void transfer(String OutName, String InName, Double money) {32: // TODO Auto-generated method stub33: accountDao.outMoney(OutName, money);34: // int i=1/0;35: accountDao.inMoney(InName, money);36: }37: }测试类:springtestdemo4.java
1: package com.spring.demo4;2: import javax.annotation.Resource;3: import org.junit.Test;4: import org.junit.runner.RunWith;5: import org.springframework.test.context.ContextConfiguration;6: import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;7: /**
8: * 声明式:基于注解的事务管理方式9: *10: * @author su11: *12: */13: @RunWith(SpringJUnit4ClassRunner.class)
14: @ContextConfiguration("classpath:applicationContext4.xml")
15: public class springtestdemo4 {16:17: //测试业务层类:18: @Resource(name="accountService")
19: private AccountService accountService;
20: @Test21: public void test(){
22: accountService.transfer("aaa", "bbb", 300d);23: }24: }