Spring的事务传播属性:
事务传播行为是Spring框架独有的事务增强特性。
1.什么是事务传播行为??
事务传播行为是用来描述由某一个事务传播行为嵌套进另一个方法时的事务如何传播。
用伪代码说明
public void methodA(){
methodB();
}
@Transaction(Propagation = xxx)
public void methodB(){
//do something
}
1.Required(默认属性):
如果存在一个事务,则支持当前事务。如果没有事务,则开启一个新的事务。
2.Supports
支持当前事务,如果当前没有事务,就以非事务的方式执行
3.MANDATORY
使用当前的事务,如果没有事务,就抛出异常
4.Requires_New
新建事务,如果当前存在事务,就把当前事务挂起。
5.Not_Supported
以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
6.Never
以非事务方式执行操作,如果当前存在事务,则抛出异常。
7.Nested
支持当前事务,新增Savepoint点,与当前事务同步提交或回滚。
嵌套事务一个非常重要的概念就是内层事务依赖于外层事务,外层事务失败时,会回滚内层事务所做的动作。而内层事务操作失败并不会引起外层事务的回滚。
代码验证
假如说我们数据库里面有两张表,user1 和user2, 列名id 和 name
连接数据库可以用mybatis或者jdbc
然后,Dao层代码:
public class User1 {
private Integer id;
private String name;
//get和set方法省略...
}
public class User2 {
private Integer id;
private String name;
//get和set方法省略...
}
User1Mapper:
public interface User1Mapper {
int insert(User1 record);
User1 selectByPrimaryKey(Integer id);
//其他方法省略...
}
User2Mapper:
public interface User2Mapper {
int insert(User2 record);
User2 selectByPrimaryKey(Integer id); //其他方法省略...
}
验证就在Service层实现
我们为User1Service和User2Service相应方法加上Propagation.REQUIRED
属性。
User1Service方法:
@Service
public class User1ServiceImpl implements User1Service {
//省略其他...
@Override
@Transactional(propagation = Propagation.REQUIRED)
public void addRequired(User1 user){
user1Mapper.insert(user);
}
}
User2Service方法:
@Service
public class User2ServiceImpl implements User2Service {
//省略其他...
@Override
@Transactional(propagation = Propagation.REQUIRED)
public void addRequired(User2 user){
user2Mapper.insert(user);
}
@Override
@Transactional(propagation = Propagation.REQUIRED)
public void addRequiredException(User2 user){
user2Mapper.insert(user);
throw new RuntimeException();
}
}
然后我们来验证:
@Override
public void notransaction_exception_required_required(){
User1 user1=new User1();
user1.setName("张三");
user1Service.addRequired(user1);
User2 user2=new User2();
user2.setName("李四");
user2Service.addRequired(user2);
throw new RuntimeException();
}
第一种,张三,李四都会插入进去,外围方法未开启事务,插入张三 李四方法在自己的事务中独立运行,外围方法异常不影响内部。
@Override
public void notransaction_required_required_exception(){
User1 user1=new User1();
user1.setName("张三");
user1Service.addRequired(user1);
User2 user2=new User2();
user2.setName("李四");
user2Service.addRequiredException(user2);
}
第二种,张三插入,李四未插入。外围方法没有事务,插入“张三”、“李四”方法都在自己的事务中独立运行,所以插入“李四”方法抛出异常只会回滚插入“李四”方法,插入“张三”方法不受影响。
结论:通过这两个方法我们证明了在外围方法未开启事务的情况下Propagation.REQUIRED
修饰的内部方法会新开启自己的事务,且开启的事务相互独立,互不干扰。