Spring-如何使用两个数据源正确配置@Transactional?

时间:2019-06-07 19:36:12

标签: java spring spring-boot

我有两个spring数据源配置,如下所示:

@EnableJpaRepositories(basePackages = {"XXXXXX",
                                       "XXXXXX"}, entityManagerFactoryRef = "postgreSqlEM", transactionManagerRef = "postgreSqlTM")
@EnableTransactionManagement
@Configuration
public class PostgreSqlDataSourceConfig {

    @Primary
    @Bean
    @ConfigurationProperties("spring.postgresql.hikari")
    public HikariConfig postgreSqlHikariConfig() {
        return new HikariConfig();
    }

    @Primary
    @Bean
    public DataSource postgreSqlDataSource() {
        return new HikariDataSource(postgreSqlHikariConfig());
    }

    @Primary
    @Bean("postgreSqlEM")
    public LocalContainerEntityManagerFactoryBean postgreSqlEntityManagerFactory(EntityManagerFactoryBuilder builder) {
        return builder.dataSource(postgreSqlDataSource()).packages("XXXXXX",
                                                                   "XXXXXX",
                                                                   "XXXXXX")

                      .build();
    }

    @Primary
    @Bean("postgreSqlTM")
    public JpaTransactionManager postgreSqlTransactionManager(@Qualifier("postgreSqlEM") EntityManagerFactory emf) {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(emf);
        return transactionManager;
    }

    @Primary
    @Bean
    public EntityManager getEntityManager(@Qualifier("postgreSqlEM") EntityManagerFactory emf) {
        return emf.createEntityManager();
    }
}

这是@Primary,所以所有没有值配置的@Transactional以及所有EntityManager注入都应指向它。

Spring启动正常启动,但是所有@Transactional注释都将被忽略。

我遇到这样的错误:

javax.persistence.TransactionRequiredException: javax.persistence.Query.executeUpdate requires active transaction

我如何正确配置它以便@Transactional工作?

我正在使用Spring Boot 2.1.5.RELEASE。

2 个答案:

答案 0 :(得分:2)

首先, 每个数据源配置一个TransactionManager。 两个数据源意味着您将拥有两个TransactionManager。

这里是一个例子:

    @Bean(name = "blamTransactionManager")
    @Primary
    public PlatformTransactionManager blamTransactionManager(
        @Qualifier("blamDataSourcePool") final DataSource blamDataSource)
    {
        return new DataSourceTransactionManager(
            blamDataSource);
    }

第二, 使用上面创建的两个事务管理器配置ChainedTransactionManager

这里是一个例子:

    @Bean(name = "chainedTransactionManager")
    public ChainedTransactionManager transactionManager(
        @Qualifier("blamTransactionManager") final PlatformTransactionManager blamTransactionManager,
        @Qualifier("kapowTransactionManager") final PlatformTransactionManager kapowTransactionManager)
    {
        return new ChainedTransactionManager(
            blamTransactionManager,
            kapowTransactionManager);
    }

最后, 请在您的事务性注释中引用chainedTransactionManager。

例如:

    @Transactional("chainedTransactionManager")

答案 1 :(得分:0)

我做过类似的事情,将与一个事务一起工作的实体放入一个单独的包中。这是配置单个数据源(我有四个不同的数据源)的方法。

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
    entityManagerFactoryRef = "firstEntityManagerFactory",
    basePackages = "com.example.repository.first"
)
public class FirstDbConfig {

    @Bean(name = "firstDataSource")
    @ConfigurationProperties(prefix = "first.datasource")
    public DataSource dataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "firstEntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean
    entityManagerFactory(
            EntityManagerFactoryBuilder builder,
            @Qualifier("firstDataSource") DataSource dataSource
    ) {
        return builder
                .dataSource(dataSource)
                .packages("com.example.domain.first")
                .persistenceUnit("first")
                .build();
    }

    @Bean(name = "firstTransactionManager")
    public PlatformTransactionManager transactionManager(
            @Qualifier("firstEntityManagerFactory") EntityManagerFactory
                    entityManagerFactory
    ) {
        return new JpaTransactionManager(entityManagerFactory);
    }

}