3-Transactional中propagation属性
作者:互联网
@Transactional注解中有很多的属性,但是大多数属性都是比较好理解的,当然除了这个propagation属性之外。
因为这个属性的值比较多,场景也比较多所以容易混淆和以往,这里就做下总结,方便以后进行复习。
虽然propagation中的值比较多,但是很多值都不常用,所以我分为两部分,一部分是常用的值,一部分是不常用的值。重点理解常用值,而非常用值面试时候使用。
propagation值
propagation的值 | 解释 | 是否常用 |
---|---|---|
Propagation.REQUIRED | ✔ | |
Propagation.SUPPORTS | ✔ | |
Propagation.MANDATORY | ❌ | |
Propagation.REQUIRES_NEW | ❌ | |
Propagation.NOT_SUPPORTED | ❌ | |
Propagation.NEVER | ❌ | |
Propagation.NESTED | ❌ |
Propagation.REQUIRED
图中所指的开始事务的意思就是添加上@Transactional注解的意思。
由于同一个类中调用带有@Transactional的方法是无效的,所以我创建了两个方法来进行测试。先测试。
Case 1情况
在ServiceAImpl.class中创建一个带有@Transactional方法,分别执行添加操作和调用方法操作
@Transactional
@Override
public void entranceHaveTransactional() {
User user= User.builder()
.id(20)
.passWord("122")
.userName("hello")
.realName("realname")
.build();
userMapper.insertOne(user);
iServer.required();
// 请注意这里,制造了一个人为的异常
throw new RuntimeException("人为制造异常");
}
在ServerImpl中创建一个方法required,并插入数据
@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
@Override
public void required() {
User user= User.builder()
.id(5)
.passWord("122")
.userName("hello")
.realName("realname")
.build();
userMapper.insertOne(user);
}
结果
这两个方法在同一个事务当中,由于entranceHaveTransactional方法抛出异常,所以两个方法的插入都没有生效,查看数据库也确实如此。
Case 2情况
@Override
public void entranceHaveTransactional() {
User user= User.builder()
.id(20)
.passWord("122")
.userName("hello")
.realName("realname")
.build();
userMapper.insertOne(user);
iServer.required();
// 请注意这里,制造了一个人为的异常
throw new RuntimeException("人为制造异常");
}
@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
@Override
public void required() {
User user= User.builder()
.id(5)
.passWord("122")
.userName("hello")
.realName("realname")
.build();
userMapper.insertOne(user);
// 这里注意 新添加了一个异常
throw new RuntimeException("required exception");
}
执行结果
id为20插入数据库成功,而id为5的没有插入成功,说明和图示描述的逻辑一致。
Propagation.REQUIRES_NEW
Case 1情况
@Transactional
@Override
public void entranceRequiredNew() {
User user= User.builder()
.id(21)
.passWord("122")
.userName("hello")
.realName("realname")
.build();
userMapper.insertOne(user);
iServer.requiredNew();
throw new RuntimeException("人为制造异常");
}
@Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor = Exception.class)
@Override
public void requiredNew() {
User user= User.builder()
.id(6)
.passWord("122")
.userName("hello")
.realName("realname")
.build();
userMapper.insertOne(user);
}
结果
id为6的数据成功插入到数据库,而id为21的的没有插入到数据库,和图示中Case 1 描述完全一致。
Case 2 情况
@Override
public void entranceRequiredNew() {
User user= User.builder()
.id(20)
.passWord("122")
.userName("hello")
.realName("realname")
.build();
userMapper.insertOne(user);
iServer.requiredNew();
throw new RuntimeException("人为制造异常");
}
@Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor = Exception.class)
@Override
public void requiredNew() {
User user= User.builder()
.id(6)
.passWord("122")
.userName("hello")
.realName("realname")
.build();
userMapper.insertOne(user);
throw new RuntimeException("requiredNew");
}
结果
id为21的数据成功插入到数据库中,而id为6的没有插入到数据库中。
说明requiredNew中的事务起了作用,而由于entranceRequiredNew没有添加事务,所以可以添加到书库中,异常不影响。
其他情况都比较少见,可以自行进行编写,进行查看。如果想看详细代码可以查看我github仓库,地址为:
https://github.com/bulingfeng/spring-cloud-demo/tree/master/spring-transactional-demo
注意事项
- 我每次测试都是把数据库中的数据进行删除,所以不存在主键冲突的情况。
- 我理解图示中的逻辑其实是主要取决于被调用方法所使用@Transactional中propagation的值,调用方法使用@Transactional代表是否开始事务(如有理解错误,请留言纠正)。
标签:Propagation,Transactional,propagation,user,属性,id,User 来源: https://www.cnblogs.com/bulingfeng/p/16416121.html