-
Spring遇到嵌套事务时,当被嵌套的事务被定义为“PROPAGATION_REQUIRES_NEW”时,内层Service方法被调用时,外层方法的事务被挂起,内层事务相对于外层事务是完全独立的,有独立的隔离性等等...Spring书上如是说的。但我在做一个实验时却遇到一个奇怪的问题,
1、当一个Service类中的某方法调用另一个Service类中某方法时,内层事务提交也好,回滚也好,都不受外层事务提交或回滚的影响。就是如果内层事务提交了,即使外层事务回滚了,内层事务提交了的数据也不会回归回来了。
2、当一个Service方法调用本Service类中的另一个方法时,内层事务貌似不能正确地提交或者回滚。
我的代码如下:
BbtForumImpl中在第8行调用BbtForumImpl自己的另一个方法,形成内嵌事务,这样的内嵌事务貌似不能如“PROPAGATION_REQUIRES_NEW”所愿那样工作。而第9行则调用另一个Service类BbtForum2Impl的bankBusiness3()方法,“PROPAGATION_REQUIRES_NEW”工作了,为什么当调用同一个Service类中的其他方法形成嵌套事务时,“PROPAGATION_REQUIRES_NEW”并不如所愿的使外层事务挂起,内层事务独立工作?而调用其它Service类的方法时内层可以独立工作了??????????????????
Serivce类 BbtForumImpl:
1) public void bankBusiness1() throws Exception
2) {
3) AgriculturalBank agriculturalBank = new AgriculturalBank();
4) agriculturalBank.setId("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
5) agriculturalBank.setMoney(new Long(0));
6) agriculturalBankDAOImpl.updateAgriculturalBank(agriculturalBank);
7)
8) this.bankBusiness2();
9)// bbtForum2.bankBusiness3();
10) throw new Exception();
11) }
12)
13) public void bankBusiness2() throws Exception
14) {
15) CommercialBank commercialBank = new CommercialBank();
16) commercialBank.setId("ccccccccccccccccccccccccccccccc");
17) commercialBank.setMoney(new Long(0));
18) commercialBankDAOImpl.updateAgriculturalBank(commercialBank);
19)
20) }
Serivce类 BbtForum2Impl:
1) public void bankBusiness3() throws Exception
2) {
3) CommercialBank commercialBank = new CommercialBank();
4) commercialBank.setId("ccccccccccccccccccccccccccccccc");
5) commercialBank.setMoney(new Long(0));
6) commercialBankDAOImpl.updateAgriculturalBank(commercialBank);
7) }
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="bbtForumTarget" class="com.baobaotao.service.impl.BbtForumImpl">
<property name="commercialBankDAOImpl" ref="commercialBankDAOImpl"/>
<property name="agriculturalBankDAOImpl" ref="agriculturalBankDAOImpl"></property>
<property name="bbtForum2" ref="bbtForum2"></property>
</bean>
<bean id="bbtForum" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="txManager"/>
<property name="target" ref="bbtForumTarget"></property>
<property name="transactionAttributes">
<props>
<prop key="bankBusiness">PROPAGATION_REQUIRED, -Exception</prop>
<prop key="bankBusiness1">PROPAGATION_REQUIRED, -Exception</prop>
<prop key="bankBusiness2">PROPAGATION_REQUIRES_NEW, -Exception</prop>
</props>
</property>
</bean>
<bean id="bbtForum2Target" class="com.baobaotao.service.impl.BbtForum2Impl">
<property name="commercialBankDAOImpl" ref="commercialBankDAOImpl"/>
</bean>
<bean id="bbtForum2" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="txManager"/>
<property name="target" ref="bbtForum2Target"></property>
<property name="transactionAttributes">
<props>
<prop key="bankBusiness3">PROPAGATION_REQUIRES_NEW, -Exception</prop>
</props>
</property>
</bean>2008年11月17日 22:59
1个答案按时间排序按投票排序
-
PROPAGATION_REQUIRED
加入当前正要执行的事务不在另外一个事务里,那么就起一个新的事务
比如说,ServiceB.methodB的事务级别定义为PROPAGATION_REQUIRED, 那么由于执行ServiceA.methodA的时候,ServiceA.methodA已经起了事务,这时调用ServiceB.methodB,ServiceB.methodB看到自己已经运行在ServiceA.methodA
的事务内部,就不再起新的事务。而假如ServiceA.methodA运行的时候发现自己没有在事务中,他就会为自己分配一个事务。这样,在ServiceA.methodA或者在ServiceB.methodB内的任何地方出现异常,事务都会被回滚。即使ServiceB.methodB的事务已经被提交,但是ServiceA.methodA在接下来fail要回滚,ServiceB.methodB也要回滚
PROPAGATION_REQUIRES_NEW
那么当执行到ServiceB.methodB的时候,ServiceA.methodA所在的事务就会挂起,ServiceB.methodB会起一个新的事务,等待ServiceB.methodB的事务完成以后,
他才继续执行。他与PROPAGATION_REQUIRED 的事务区别在于事务的回滚程度了。因为ServiceB.methodB是新起一个事务,那么就是存在
两个不同的事务。如果ServiceB.methodB已经提交,那么ServiceA.methodA失败回滚,ServiceB.methodB是不会回滚的。如果ServiceB.methodB失败回滚,
如果他抛出的异常被ServiceA.methodA捕获,ServiceA.methodA事务仍然可能提交。