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事务的传播关系。网上有很多传播的关系,但是都讲的云里雾里的。所以特此文章记录一下。
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事务隔离、传播
- spring事务传播机制
- Spring事务的传播特性和隔离级别
- Spring的 事务传播行为类型
- spring事务传播属性与隔离级别
- <转>Spring事务传播机制
- Spring五个事务隔离级别和七个事务传播行为
- Spring事务的传播特性
- spring事务传播之NESTED
- Spring事务传播机制
- spring 的事务传播机制
- Spring事务的传播特性以及事务的隔离级别
- Spring事务总结---传播级别以及REQUIRED_NEW及NESTED的使用场景(赞)
- Spring事务隔离和事务传播
- spring-事务传播特性
- Spring事务的传播行为和隔离级别
- spring 事务传播问题
- Spring事务传播机制和数据库隔离级别
- Spring事务的传播行为 @Transactional(转)
- SPRING的事务传播特性