Spring Boot 项目中配置多数据源@Transactio

2019-03-27  本文已影响0人  studymachine

现象 :

当一个Spring Boot 项目在配置了多个数据源 , 在编写Service层方法的时候 , 直接在service方法的上添加的@Transactional直接实现事务管理的方式是失效的 .

原因 :

以最近接触到的一个持久层框架使用的是Jpa的项目为例 , 该项目通过硬编码(配置类)的方式 , 在项目中配置了两个不同的数据源 , 所以这个项目分别根据两个数据源配置了各自的事务管理器PlatformTransactionManager , 如下 :

第一个数据源的事务管理器配置类 :

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "entityManagerFactoryOne",
        transactionManagerRef = "transactionManagerOne",
        basePackages = {"com.xxx.xxx"} 
)
public class OneDataSourceConfig {

    @Autowired
    @Qualifier("oneDataSource")
    private DataSource oneDataSource;
    

   // .. 这里省略部分bean配置

    @Bean(name = "transactionManagerOne")
    public PlatformTransactionManager transactionManager(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(entityManagerFactoryBean(builder).getObject());
    }
}

第二个数据源事务管理器配置类 :

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "entityManagerFactoryTwo", //实体管理
        transactionManagerRef = "transactionManagerTwo", //事务管理
        basePackages = {"com.xxx"} //数据源所应用到的包
)
public class WeeklyDataSourceConfig {

    @Autowired
    @Qualifier("weeklyDataSource")
    private DataSource weeklyDataSource;
    
    //这里省略部分配置 ...
    
    @Primary
    @Bean(name = "transactionManagerTwo")
    public PlatformTransactionManager transactionManager(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(entityManagerFactoryBean(builder).getObject());
    }
}

可以看到第二个事务管理器的Bean方法上添加了@Primary注解 , 所以在通过PlatformTransactionManager类型注入事务管理器的bean时 , 默认是根据类型去注入 , 如果该类型有多个Bean , 如不通过bean的名字去注入 , 则默认是会注入被@Primary标识的bean的 ;

所以在这个项目中 , 当在业务层方法添加@Transactional注解时 , 默认是调用了transactionManagerTwo这个bean , 而我在编写service层的方法时 , 调用的是第一个数据源对应的Dao层方法 , 所以直接添加@Transactional是不能实现事务管理的 ,

解决办法 :

需要在使用@Transactional注解时指定使用的事务管理器的bean的名字 , 比如我这里调用的是第一个数据源的dao层方法 , 所以需要指定对应的事务管理器 : @Transactional(transactionManager = "transactionManagerOne") .

@Transactional(transactionManager = "transactionManagerOne")
    public void deleteById(Integer Id) {
       //...
    }
上一篇下一篇

猜你喜欢

热点阅读