Spring事务传播

在TransactionDefinition接口中定义了七个事务传播行为

PROPAGATION_REQUIRED 如果存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务。默认行为

PROPAGATION_SUPPORTS 如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行。但是对于事务同步的事务管理器,PROPAGATION_SUPPORTS与不使用事务有少许不同。

PROPAGATION_MANDATORY 如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。

PROPAGATION_REQUIRES_NEW 总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起。

PROPAGATION_NOT_SUPPORTED 总是非事务地执行,并挂起任何存在的事务。

PROPAGATION_NEVER 总是非事务地执行,如果存在一个活动事务,则抛出异常

PROPAGATION_NESTED如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务, 则按TransactionDefinition.PROPAGATION_REQUIRED 属性执行

 

本文重点讲解PROPAGATION_REQUIRED 、PROPAGATION_REQUIRES_NEW、 PROPAGATION_NESTED

实际应用中常常存在serviceA调用serviceB的情况。那具体情况下serviceA和serviceB之间的事务又是怎么传递的呢。

例子1:

/** 事务默认是required*/
//@Transactional
@Service("userService")
public class UserServiceImpl implements UserServive {
@Autowired
private UserMapper userDao;


@Autowired
private CommonService commonService;


public List<UserInfo> getUsers() {

return userDao.selectUsers();
}

@Transactional(propagation = Propagation.REQUIRED)
public void updateUserAgeById(int age, long id) {

userDao.updateUserInfoById(age, id);

commonService.updateUserExtById("未知", 1);

//int b = 1/0;

/* try {
commonService.updateUserExtById("未知", 1);
} catch (Exception e) {
// TODO: handle exception
}*/
}
}

//@Transactional
@Service("commonService")
public class CommonServiceImpl implements CommonService {

@Autowired
private UserMapper userDao;

// 如果出现运行时异常,此处会回滚 并对外抛出异常
@Transactional(propagation = Propagation.NESTED)
public void updateUserExtById(String address, long id) {

userDao.updateUserExtById(address, id);

int a = 1/0;
}
}

此例userservice中的updateUserAgeById事务声明为Propagation.REQUIRED,调用commonservice中的updateUserExtById方法。且此方法事务声明为Propagation.NESTED。按上面的解释commonservice将运行在嵌套事务中。经过测试,当updateUserExtById

发生异常时,自身进行回滚操作,回滚到它执行之前的savepoint。并向外抛出异常,userservice可以对异常进行捕获视情况选择回滚还是不回滚。如果不进行任何处理同样数据会发生回滚。

例子2:

@Transactional(propagation = Propagation.REQUIRED)
public void updateUserAgeById(int age, long id) {

userDao.updateUserInfoById(age, id);

commonService.updateUserExtById("未知", 1);

int b = 1/0;

 

// 如果出现运行时异常,此处会回滚 并对外抛出异常
@Transactional(propagation = Propagation.NESTED)
public void updateUserExtById(String address, long id) {

userDao.updateUserExtById(address, id);

//int a = 1/0;
}

异常发生在userservice方法中,因为属于嵌套事务,所以userservice和commonservice都会发生回滚。

例子3:

 

@Transactional(propagation = Propagation.REQUIRED)
public void updateUserAgeById(int age, long id) {

userDao.updateUserInfoById(age, id);

commonService.updateUserExtById("未知", 1);

//int b = 1/0;

 

// 如果出现运行时异常,此处会回滚 并对外抛出异常
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void updateUserExtById(String address, long id) {

userDao.updateUserExtById(address, id);

int a = 1/0;
}

此处模拟的是commonservice使用的是Propagation.REQUIRES_NEW。userservice中的事务会被挂起。commonservice会新开一个事务。经过测试,此处模拟commonservice异常,其对应的事务会回滚。同样此处会对外抛出异常,userservice视情况对异常处理,选择回滚还是不回滚。

例子4:

 

@Transactional(propagation = Propagation.REQUIRED)
public void updateUserAgeById(int age, long id) {

userDao.updateUserInfoById(age, id);

commonService.updateUserExtById("未知", 1);

int b = 1/0;

 

// 如果出现运行时异常,此处会回滚 并对外抛出异常
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void updateUserExtById(String address, long id) {

userDao.updateUserExtById(address, id);

//int a = 1/0;
}

此处模拟userservice发生异常。我们猜测一下commonservice会不会回滚。经过试验得到结果是commonservice不会回滚。因为在userservice发生异常前。commonservice的事务已经commit。

例子5:

@Transactional(propagation = Propagation.REQUIRED)
public void updateUserAgeById(int age, long id) {

userDao.updateUserInfoById(age, id);

//commonService.updateUserExtById("未知", 1);

//int b = 1/0;

try {
commonService.updateUserExtById("未知", 1);
} catch (Exception e) {
// TODO: handle exception
}
}

@Transactional(propagation = Propagation.REQUIRED)
public void updateUserExtById(String address, long id) {

userDao.updateUserExtById(address, id);

int a = 1/0;
}

最后再来看看同用Propagation.REQUIRED的情况。此处模拟commonservice异常,不用怀疑commonservice肯定会回滚。但是此处userservice进行了异常捕获,userservice还会回滚吗?答案会。两者用的是一个事务,commonservice发生异常,整个事务直接rollback。

好了,大概清楚了spring事务的传播关系。网上有很多传播的关系,但是都讲的云里雾里的。所以特此文章记录一下。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值