相关代码: Spring事务传播特性代码 GitHub
REQUIRED如果当前没有开启事务,就开启一个新事务,如果当前开启了事务,就加入该事务。
- Service层代码:
@Service("deptService")
public class DeptServiceImpl implements DeptService {
@Resource
private DeptMapper deptMapper;
@Override
@Transactional(propagation = Propagation.REQUIRED)
public int deleteByDeptno(Integer deptno) {
deptMapper.deleteByPrimaryKey(deptno);
throw new RuntimeException("数据删除出错"); //模拟出错
}
@Resource(name = "deptService")
private DeptService deptService;
@Override
//@Transactional(propagation = Propagation.REQUIRED)
public int save(Dept record) {
int res1 = deptMapper.insert(record);//插入
int res2 = deptService.deleteByDeptno(84);//更新
System.out.println(3 / 0); //模拟出错
return res1 + res2;
}
}
- 测试代码:
@SpringBootTest
class DeptServiceImplTest {
@Resource(name = "deptService")
private DeptService deptService;
@Test
void insert() {
Dept dept = Dept.builder()
.dname("bb")
.loc("bbbbbbbbb").build();
int insert = deptService.save(dept);
System.out.println(insert);
}
}
如果save()方法没有开启事务,insert()方法不会回滚,delete()方法开启了事务,delete会回滚。 如果save()方法开启了事务,则delete()方法不会开启新事务,会加入到save()方法的事务中,insert()方法和delete()方法都会回滚。
SUPPORTS如果当前开启了事务,就加入该事务,否则非事务执行。
- Service代码:
@Service("deptService5")
public class DeptServiceImpl implements DeptService {
@Resource
private DeptMapper deptMapper;
@Override
@Transactional(propagation = Propagation.SUPPORTS)
public int deleteByDeptno(Integer deptno) {
deptMapper.deleteByPrimaryKey(deptno);
throw new RuntimeException("数据删除出错"); //模拟出错
}
@Resource(name = "deptService")
private DeptService deptService;
@Override
public int save(Dept record) { //没有开启事务
int res1 = deptMapper.insert(record);//插入
int res2 = deptService.deleteByDeptno(84);//更新
System.out.println(3 / 0); //模拟出错
return res1 + res2;
}
}
- 测试代码:
@SpringBootTest
class DeptServiceImplTest {
@Resource(name = "deptService")
private DeptService deptService;
@Test
void insert() {
Dept dept = Dept.builder()
.dname("bb")
.loc("bbbbbbbbb").build();
int insert = deptService.save(dept);
System.out.println(insert);
}
}
如果save()方法没有开启事务,delete()方法也不会开启事务,insert()方法和delete()方法操作均不会回滚。 如果save()方法开启了事务,delete()方法会加入到save()方法的事务中,则insert()方法和delete()方法均会回滚。
MANDATORY如果当前开启了事务,就加入该事务,否则抛出异常。说白了,强制事务,不允许非事务执行。
- Service代码:
@Service("deptService")
public class DeptServiceImpl implements DeptService {
@Resource
private DeptMapper deptMapper;
@Override
@Transactional(propagation = Propagation.MANDATORY)
public int deleteByDeptno(Integer deptno) {
deptMapper.deleteByPrimaryKey(deptno);
throw new RuntimeException("数据删除出错"); //模拟出错
}
@Resource(name = "deptService")
private DeptService deptService;
@Override
public int save(Dept record) {
int res1 = deptMapper.insert(record);//插入
int res2 = deptService.deleteByDeptno(87);//更新
System.out.println(3 / 0); //模拟出错
return res1 + res2;
}
}
- 测试代码:
@SpringBootTest
class DeptServiceImplTest {
@Resource(name = "deptService")
private DeptService deptService;
@Test
void insert() {
Dept dept = Dept.builder()
.dname("bb")
.loc("bbbbbbbbb").build();
int insert = deptService.save(dept);
System.out.println(insert);
}
}
如果save()方法没有开启事务,执行delete()方法时会抛出异常:insert()方法成功,delete()方法操作没有执行。 如果save()方法开启了事务,则delete()方法加入到事务中,不会抛异常。
REQUIRES_NEW如果当前没有开启事务,则开启一个新事务来执行。 如果当前开启了事务,则将当前事务挂起,开启一个新事务来执行。 外层事务和内层事务是互相隔离的,内层事务的提交或回滚不影响外层事务,外层事务的提交或回滚也不影响内层事务。 需要捕获内层方法异常,否则内层方法抛异常,会影响外层事务回滚。
- Service代码:
@Service("deptService")
public class DeptServiceImpl implements DeptService {
@Resource
private DeptMapper deptMapper;
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public int deleteByDeptno(Integer deptno) {
return deptMapper.deleteByPrimaryKey(deptno);
}
@Resource(name = "deptService")
private DeptService deptService;
@Override
@Transactional
public int save(Dept record) {
int res1 = deptMapper.insert(record);//插入
int res2 = deptService.deleteByDeptno(87);//更新
System.out.println(3 / 0); //模拟出错
return res1 + res2;
}
}
- 测试代码:
@SpringBootTest
class DeptServiceImpl9Test {
@Resource(name = "deptService")
private DeptService deptService;
@Test
void insert() {
Dept dept = Dept.builder()
.dname("bb")
.loc("bbbbbbbbb").build();
int insert = deptService.save(dept);
System.out.println(insert);
}
}
save()方法开启了事务A,执行delete()时,会将save()方法的事务A挂起,并开启新事务B,delete()方法执行成功,事务B提交,然后恢复事务A,接着抛出异常,事务A回滚,但是事务B已经提交不会受到影响。最终delete()方法操作成功,insert()方法操作被回滚。
NOT_SUPPORTED强制以非事务方式执行,如果当前开启了事务就将当前事务挂起再执行。
- Service代码:
@Service("deptService")
public class DeptServiceImpl10 implements DeptService {
@Resource
private DeptMapper deptMapper;
@Override
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public int deleteByDeptno(Integer deptno) {
int res = deptMapper.deleteByPrimaryKey(deptno);
System.out.println(2/0);
return res;
}
@Resource(name = "deptService")
private DeptService deptService;
@Override
@Transactional
public int save(Dept record) {
int res1 = deptMapper.insert(record);//插入
int res2 = deptService.deleteByDeptno(88);//更新
System.out.println(3 / 0); //模拟出错
return res1 + res2;
}
}
- 测试代码:
@SpringBootTest
class DeptServiceImpl10Test {
@Resource(name = "deptService")
private DeptService deptService;
@Test
void insert() {
Dept dept = Dept.builder()
.dname("bb")
.loc("bbbbbbbbb").build();
int insert = deptService.save(dept);
System.out.println(insert);
}
}
save()方法开启了事务,执行delete()方法时会挂起事务,然后以非事务的方式执行delete()方法并提交,然后恢复事务,由于save()方法抛出异常,insert回滚。 结果insert()方法回滚、delete()方法正常提交。
NEVER:非事务执行,如果当前开启了事务则抛出异常。- Service代码:
@Service("deptService")
public class DeptServiceImpl implements DeptService {
@Resource
private DeptMapper deptMapper;
@Override
@Transactional(propagation = Propagation.NEVER)
public int deleteByDeptno(Integer deptno) {
int res = deptMapper.deleteByPrimaryKey(deptno);
System.out.println(2/0);
return res;
}
@Resource(name = "deptService")
private DeptService deptService;
@Override
@Transactional
public int save(Dept record) {
int res1 = deptMapper.insert(record);//插入
int res2 = deptService.deleteByDeptno(88);//更新
System.out.println(3 / 0); //模拟出错
return res1 + res2;
}
}
- 测试代码:
@SpringBootTest
class DeptServiceImpl11Test {
@Resource(name = "deptService")
private DeptService deptService;
@Test
void insert() {
Dept dept = Dept.builder()
.dname("bb")
.loc("bbbbbbbbb").build();
int insert = deptService.save(dept);
System.out.println(insert);
}
}
- 如果save()方法开启了事务,导致delete()方法抛出异常:
- 如果save()方法没有开启事务,则save()方法和delete()方法都会以非事务执行。
如果方法没有开启事务,则开启一个新事务来执行,否则,在当前事务中以嵌套事务的方式执行。嵌套事务执行前,会创建一个保存点savePoint,如果方法异常,则回滚到该savePoint,否则等待和外层事务一起Commit。
- Service代码:
@Service("deptService")
public class DeptServiceImpl implements DeptService {
@Resource
private DeptMapper deptMapper;
@Override
@Transactional(propagation = Propagation.NESTED)
public int deleteByDeptno(Integer deptno) {
int res = deptMapper.deleteByPrimaryKey(deptno);
System.out.println(2 / 0);
return res;
}
@Resource(name = "deptService")
private DeptService deptService;
@Override
@Transactional
public int save(Dept record) {
int res1 = deptMapper.insert(record);//插入
int res2 = 0;//更新
try {//delete执行前,保存一个savePoint,如果delete异常,则回滚到savePoint,否则等待和save一起提交事务
res2 = deptService.deleteByDeptno(88);
} catch (Exception e) {
e.printStackTrace();
}
//System.out.println(3 / 0); //模拟出错,如果出错insert和delete会一起回滚
return res1 + res2;
}
}
- 测试代码:
@SpringBootTest
class DeptServiceImpl12Test {
@Resource(name = "deptService12")
private DeptService deptService;
@Test
void insert() {
Dept dept = Dept.builder()
.dname("bb")
.loc("bbbbbbbbb").build();
int insert = deptService.save(dept);
System.out.println(insert);
}
}
如果3/0行代码不注释,则出错,insert和delete方法都回滚;否则都正常提交。