springboot多个service互相调用的事务处理方式

pringboot多个service互相调用的事务处理方式

目录多个service互相调用的事务处理注解配置如下Spring事务调用Service和Service之间的调用原理解析

今天,想在一个service的方法A中,调用另一个service的方法B,方法A和方法B均存在数据库插入操作,并且@Transaction注解也都加了,但是当B方法中抛出异常时,A中的插入语句还是能够执行成功。

注解配置如下

@Transactional(isolation= Isolation.DEFAULT,propagation= Propagation.REQUIRED)

百思不得其解,再查找了相关资料后,问题还是出在@Transaction注解的配置上,需要配置异常回滚。

@Transactional(isolation= Isolation.DEFAULT,propagation= Propagation.REQUIRED,rollbackFor = Exception.class)

这样,当B方法中抛出异常时,A中的操作也会进行回滚,事务就会起到控制作用。

Spring事务调用Service和Service之间的调用

同一个类的不同方法,A方法没有@Transactional,B方法有@Transactional,A调用B方法,事务不起作用

原理解析

spring 在扫描bean的时候会扫描方法上是否包含@Transactional注解,如果包含,spring会为这个bean动态地生成一个子类(即代理类,proxy),代理类是继承原来那个bean的。

此时,当这个有注解的方法被调用的时候,实际上是由代理类来调用的,代理类在调用之前就会启动thttp://ransaction。

然而,如果这个有注解的方法是被同一个类中的其他方法调用的,那么该方法的调用并没有通过代理类,而是直接通过原来的那个bean,所以就不会启动transaction,我们看到的现象就是@Transactional注解无效。

//接口

interface Service {

void A();

void B();

}

//目标类,实现接口

class ServiceImpl implements Service {

//no annotation here

@Override

public void A() {

this.B();

}

@Transactional

@Override

public void B() {

System.out.println("execute doNeedTx in ServiceImpl");

}

}

//代理类,也要实现相同的接口

class ProxyByJdkDynamic implements Service {

//包含目标对象

private Service target;

public ProxyByJdkDynamic(Sehttp://rvice target) {

this.target = target;

}

//目标类中此方法带注解,进行特殊处理

@Override

public void B() {

//开启事务

System.out.println("-> create Tx here in Proxy");

//调用目标对象的方法,该方法已在事务中了

target.B();

//提交事务

System.out.println("<- commit Tx here in Proxy");

}

//目标类中此方法没有注解,只做简单的调用

@Override

public void A() {

//直接调用目标对象方法

target.A();

}

}

那回到一开始的问题,我们调用的方法A不带注解,因此代理类不开事务,而是直接调用目标对象的方法。

当进入目标对象的方法后,执行的上下文已经变成目标对象本身了,因为目标对象的代码是我们自己写的,和事务没有半毛钱关系,此时你再调用带注解的方法,照样没有事务,只是一个普通的方法调用而已。

简单来说,内部调用本类方法,不会再走代理了,所以B的事务不起作用

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot中,可以通过使用`@Transactional`注解来管理多个数据源的事务。首先,需要在配置文件中定义多个数据源,并将它们分别配置为`DataSource` bean。然后,可以使用`@Transactional`注解在需要进行事务管理的方法上进行标记。 在使用`@Transactional`注解时,可以指定`transactionManager`属性来指定使用的事务管理器。可以为每个数据源配置一个事务管理器,并在不同的方法上使用不同的事务管理器。例如: ```java @Configuration @EnableTransactionManagement public class DataSourceConfig { @Bean @ConfigurationProperties(prefix = "datasource1") public DataSource dataSource1() { return DataSourceBuilder.create().build(); } @Bean @ConfigurationProperties(prefix = "datasource2") public DataSource dataSource2() { return DataSourceBuilder.create().build(); } @Bean(name = "transactionManager1") public PlatformTransactionManager transactionManager1() { return new DataSourceTransactionManager(dataSource1()); } @Bean(name = "transactionManager2") public PlatformTransactionManager transactionManager2() { return new DataSourceTransactionManager(dataSource2()); } } ``` 然后,在需要进行事务管理的方法上使用`@Transactional`注解,并指定使用的事务管理器。例如: ```java @Service public class MyService { @Autowired private MyRepository repository; @Transactional(transactionManager = "transactionManager1") public void method1() { // 使用第一个数据源执行数据库操作 repository.save(entity1); } @Transactional(transactionManager = "transactionManager2") public void method2() { // 使用第二个数据源执行数据库操作 repository.save(entity2); } } ``` 这样,当调用`method1()`时,将使用第一个数据源和对应的事务管理器来管理事务调用`method2()`时,将使用第二个数据源和对应的事务管理器来管理事务。这样就可以实现多数据源的事务管理。注意,`@Transactional`注解应该放在具体的方法上,而不是放在类级别上。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值