您的位置:首页 > 编程语言 > Java开发

Spring事务传播

2017-08-22 21:21 134 查看
在TransactionDefinition接口中定义了七个事务传播行为。

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

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

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

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

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

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

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

本文重点讲解PROPAGATION_REQUIRED 、[b]PROPAGATION_REQUIRES_NEW、 [b]PROPAGATION_NESTED[/b][/b]

实际应用中常常存在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。按上面的解释[b]commonservice将运行在嵌套事务中。经过测试,当[b]updateUserExtById[/b][/b]

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

[b][b]例子2:[/b][/b]

@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根本不会抛出异常。两者用的是一个事务,commonservice发生异常,整个事务直接rollback。

好了,大概清楚了spring事务的传播关系。网上有很多传播的关系,但是都讲的云里雾里的。所以特此文章记录一下。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  spring 事务传播