spring事物的传播方式主要有以下几种:
PROPAGATION_REQUIRED:支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
PROPAGATION_SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY:支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED:支持当前事务,如果当前事务存在,则执行一个嵌套事务,如果当前没有事务,就新建一个事务。
下面我建一个web工程开始测试以上几种事物。
TestService:主要是往aa表中插入一条数据,然后调用TestService2的outterYesSave方法。
package com.syz.tx.service;
import org.springframework.jdbc.core.JdbcTemplate;
public class TestService {
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
private TestService2 testService2;
public void setTestService2(TestService2 testService2) {
this.testService2 = testService2;
}
public void currYesSave() {
String sql = "insert into aa(name,gold) values(?,?)";
jdbcTemplate.update(sql, new Object[] { "cur_yes", 100.0 });
testService2.outterYesSave();
}
}
TestService2:往bb表中插入一条数据。
package com.syz.tx.service;
import org.springframework.jdbc.core.JdbcTemplate;
public class TestService2 {
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public void outterYesSave() {
String sql = "insert into bb(name,money) values(?,?)";
jdbcTemplate.update(sql, new Object[] { "out_yes", 200.0 });
}
}
开始测试:
1.TestService.currYesSave:propagation="REQUIRED",TestService2.outterYesSave:propagation="REQUIRED"
调用TestService.currYesSave执行结果:
可以看到执行TestService.currYesSave时创建了一个事物,而TestService2.outterYesSave时,它直接引用了上面已经存在的事物。解释了:PROPAGATION_REQUIRED:支持当前事务。
2.TestService.currYesSave:propagation="SUPPORTS",TestService2.outterYesSave:propagation="REQUIRED"
调用TestService.currYesSave执行结果:
可以看到执行TestService.currYesSave时,直接创建了一个连接就执行了sql,此处没有开启事物。解释了:PROPAGATION_SUPPORTS:如果当前没有事务,就以非事务方式执行。执行TestService2.outterYesSave时创建了一个事物。解释了:PROPAGATION_REQUIRED:如果当前没有事务,就新建一个事务。
3.TestService.currYesSave:propagation="REQUIRED",TestService2.outterYesSave:propagation="SUPPORTS"
调用TestService.currYesSave执行结果:
可以看到执行TestService.currYesSave时,创建了一个事物。执行TestService2.outterYesSave时直接引用了上面已经存在的事物。解释了:PROPAGATION_SUPPORTS:支持当前事务。
4.TestService.currYesSave:propagation="REQUIRED",TestService2.outterYesSave:propagation="MANDATORY"
调用TestService.currYesSave执行结果:
可以看到执行TestService.currYesSave时,创建了一个事物。执行TestService2.outterYesSave时直接引用了上面已经存在的事物。解释了:PROPAGATION_MANDATORY:支持当前事务。
5.TestService.currYesSave:propagation="SUPPORTS",TestService2.outterYesSave:propagation="MANDATORY"
调用TestService.currYesSave执行结果:
可以看到执行TestService.currYesSave时,直接就执行了sql。执行TestService2.outterYesSave时,发现没有事物,直接就报异常了。解释了:PROPAGATION_MANDATORY:如果当前没有事务,就抛出异常。在这里说一下此次数据库的数据,aa表新加了一条数据,bb表没有。
6.TestService.currYesSave:propagation="SUPPORTS",TestService2.outterYesSave:propagation="REQUIRES_NEW"
调用TestService.currYesSave执行结果:
7.TestService.currYesSave:propagation="REQUIRED",TestService2.outterYesSave:propagation="REQUIRES_NEW"
调用TestService.currYesSave执行结果:
可以看到执行TestService.currYesSave时,创建了一个事物。执行TestService2.outterYesSave时,挂起当前事物,新建了一个事物。解释了:PROPAGATION_REQUIRES_NEW:如果当前存在事务,把当前事务挂起。
8.TestService.currYesSave:propagation="REQUIRED",TestService2.outterYesSave:propagation="NOT_SUPPORTED"
调用TestService.currYesSave执行结果:
9.TestService.currYesSave:propagation="REQUIRED",TestService2.outterYesSave:propagation="NEVER"
调用TestService.currYesSave执行结果:
可以看到执行TestService.currYesSave时,创建了一个事物。执行TestService2.outterYesSave时,直接就抛出异常了。解释了:PROPAGATION_NEVER:如果当前存在事务,则抛出异常。此时数据库中aa和bb都没有加进数据。aa插入语句回滚了,bb插入语句没执行。
10.TestService.currYesSave:propagation="SUPPORTS",TestService2.outterYesSave:propagation="NEVER"
调用TestService.currYesSave执行结果:
可以看到执行TestService.currYesSave时,直接执行了sql。执行TestService2.outterYesSave时,直接直接执行了sql。解释了:PROPAGATION_NEVER:以非事务方式执行。
11.TestService.currYesSave:propagation="SUPPORTS",TestService2.outterYesSave:propagation="NESTED"
调用TestService.currYesSave执行结果:
可以看到执行TestService.currYesSave时,直接执行了sql。执行TestService2.outterYesSave时,新建了一个事物。解释了:PROPAGATION_NESTED:如果当前没有事务,就新建一个事务。
12.TestService.currYesSave:propagation="REQUIRED",TestService2.outterYesSave:propagation="NESTED"
调用TestService.currYesSave执行结果:
可以看到执行TestService.currYesSave时,创建了一个事物。执行TestService2.outterYesSave时,创建了一个嵌套事物。解释了:PROPAGATION_NESTED:支持当前事务,如果当前事务存在,则执行一个嵌套事务。那么此时创建了几个事物呢?答案是一个,注意和PROPAGATION_REQUIRES_NEW的区别,这里是Create nested transaction,而REQUIRES_NEW是Create new transaction,故7中有两个事物。
测试完了,说一下感受吧。虽然事物的传播方式有7种,但我们经常用的估计就两种,REQUIRED和SUPPORTS,对于有更新操作的设置为REQUIRED,其它都设置为SUPPORTS,一般就能满足我们的需求了。
以上是ServiceA.methodA中调用ServiceB.methodB的情况,下面我们来看看ServiceA.methodA中调用ServiceA.methodB的情况:
TestService3:methodA向aa表插入数据,然后调用methodB。mehtodB向bb表插入数据。
package com.syz.tx.service;
import org.springframework.jdbc.core.JdbcTemplate;
public class TestService3 {
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public void methodA() {
String sql = "insert into aa(name,gold) values(?,?)";
jdbcTemplate.update(sql, new Object[] { "cur_yes", 100.0 });
methodB();
}
public void methodB() {
String sql = "insert into bb(name,money) values(?,?)";
jdbcTemplate.update(sql, new Object[] { "out_yes", 200.0 });
}
}
1.TestService3.mehtodA:propagation="SUPPORTS",TestService3.methodB:propagation="REQUIRES_NEW"
调用TestService3.methodA结果:
可以看到执行TestService3.methodA时,直接执行了sql,执行TestService3.methodB时,也是直接执行了sql。测试结果:完全没有创建事物。
2.TestService3.mehtodA:propagation="SUPPORTS",TestService3.methodB:propagation="REQUIRES_NEW"
调用TestService3.methodA结果:
可以看到执行TestService3.methodA时,创建了一个事物。执行TestService3.methodB时,直接执行了sql。测试结果:只创建了一个事物。
总结:通过以上两个测试,可以得出结论,在同一个类中,嵌套调用本类的其它方法,相当于直接把嵌套方法复制到了当前方法。对于是否创建了事物,得看当前方法有没有事物。如1,methodA无事物,调用methodB,结果没有创建事物;又如2,methodA有事物,调用methodB,结果methodB被合并到methodA了,共用一个事物。