java spring嵌套事务详情和事务传播类型

一个有事务的方法,去调用另一个有事务的方法,会怎么样?

一个没有事务的方法,去调用一个有事务的方法,会怎么样?

多事务嵌套问题解答
1、在同一个类中,一个无事务方法调用另一个有事务注解方法(比如@Async,@Transational)的方法,注解事务是不会生效的
2、在同一个类中,一个有事务方法调用另一个有事务注解方法(比如@Async,@Transational)的方法,只有外层事务有效,被调的注解事务是不会生效的
3、在不同类中,一个无事务方法调用另一个有事务注解方法(比如@Async,@Transational)的方法,有注解事务是生效的
4、在不同类中,一个有事务方法调用另一个有事务注解方法(比如@Async,@Transational)的方法,两个方法都有事务

代码示例:
@Service
public class PersonServiceImpl implements PersonService {
 
 @Autowired
 PersonDao personDao;
 
 @Override
 @Transactional
 public boolean addPerson(Person person) {
  boolean result = personDao.insertPerson(person)>0 ? true : false;
  return result;
 }
 
 @Override
 @Transactional
 public boolean updatePersonByPhoneNo(Person person) {
  boolean result = personDao.updatePersonByPhoneNo(person)>0 ? true : false;
  addPerson(person); //测试同一个类中@Transactional是否起作用
  return result;
 }
}

上述的情况,说白了,就是在一个Service内部,事务方法之间的嵌套调用,不管被调用普通方法和事务方法,都不会开启新的事务!

spring 在扫描bean的时候会扫描方法上是否包含@Transactional注解,如果包含,spring会为这个bean动态地生成一个类(即代理类,proxy),代理类是继承原来那个bean的。此时,当这个有注解的方法被调用的时候,实际上是由代理类来调用的,代理类在调用之前就会启动transaction。然而,如果这个有注解的方法是被同一个类中的其他方法调用的,那么该方法的调用并没有通过代理类,而是直接通过原来的那个bean,所以就不会启动transaction,我们看到的现象就是@Transactional注解无效。

总结:spring采用动态代理机制来实现事务控制,动态代理最终都是要调用原始对象的,而原始对象在去调用方法时,是不会再触发代理了!
重点:自己也可以实现一个事务,原理就是AOP中的动态代理

 

解决的嵌套事务方法就简单了(两种):

第一种方法:把这两个方法分开到不同的类中,把注解加到类名上面;-------不可取
第二种方法:---------可行
(1)、当这个接口没有父类,那么可以依赖注入自己 
@Autowired @Resource等,在方法中利用注入对象调用其他方法
(2)、当这个接口有父类,那么可以注入自己父类或者自己@Autowired @Resource等,然后在方法中利用注入对象调用其他方法

现在一个类里两个方法。A方法调用到B方法,要对两个方法都要切面对方法进行增强,所以也可以使用该方法
可以参考地址:
https://blog.csdn.net/levae1024/article/details/82998386
https://www.jianshu.com/p/0da29e4f354a

Spring事务7种传播属性:
REQUIRED(require)默认级别:不存在事务则创建一个事务
REQUIRES_NEW(requires_new):新建一个自己的事务,不论当前是否存在事务,已存在的事务挂起
NESTED(nested):存在事务则运行在嵌套事务中,不管是调用者还是被调用者不存在则创建一个事务
SUPPORTS(supports):存在事务则加入,不存在也可以
NOT_SUPPORT(not_support):以非事务方式运行,如果当前存在事务,则把当前事务挂起
MANDATORY(mandatory):如果当前存在事务,则运行在当前事务中,如果当前无事务,则抛出异常,也即父级方法必须有事务
NEVER(never):当前方法不能运行在事务中,存在事务则抛出异常

代码中实现:
 @Override
 @Transactional(propagation = Propagation.REQUIRED)
    public void addEmpByRequired(String name) {
        Employee employee = new Employee();
        employee.setDeptId(1);
        employee.setName(name);
        employee.setAddress("邯郸");
        employeeMapper.insertSelective(employee);
        departmentService.addDept("jishubu");
        int i = 1/0;
 }

详细实战地址如下:
https://blog.csdn.net/qq_26323323/article/details/81908955

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值