需要配置我的JPA层以使用TransactionManager(Spring Cloud Task +批处理意外注册PlatformTransactionManager) [英] Need to configure my JPA layer to use a TransactionManager (Spring Cloud Task + Batch register a PlatformTransactionManager unexpectedly)

查看:504
本文介绍了需要配置我的JPA层以使用TransactionManager(Spring Cloud Task +批处理意外注册PlatformTransactionManager)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在项目中使用Spring Cloud Task + Batch. 我计划对任务使用业务数据和Spring审核数据的不同数据源.所以我配置了类似的东西:

I am using Spring Cloud Task + Batch in a project. I plan to use different datasources for business data and Spring audit data on the task. So I configured something like:

   @Bean
   public TaskConfigurer taskConfigurer() {
       return new DefaultTaskConfigurer(this.singletonNotExposedSpringDatasource());
   }

   @Bean
   public BatchConfigurer batchConfigurer() {
       return new DefaultBatchConfigurer(this.singletonNotExposedSpringDatasource());
   }

而主数据源是通过JpaBaseConfiguration自动配置的.

whereas main datasource is autoconfigured through JpaBaseConfiguration.

SimpleBatchConfiguration + DefaultBatchConfigurer公开PlatformTransactionManager bean时出现问题,因为JpaBaseConfigurationPlatformTransactionManager上具有@ConditionalOnMissingBean.因此,绑定到spring.datasourceBatch's PlatformTransactionManager发生了.

The problem comes when SimpleBatchConfiguration+DefaultBatchConfigurer expose a PlatformTransactionManager bean, since JpaBaseConfiguration has a @ConditionalOnMissingBean on PlatformTransactionManager. Therefore Batch's PlatformTransactionManager, binded to the spring.datasource takes place.

到目前为止,这似乎是由于

So far, this seems to be caused because this bug

因此,我尝试模仿JpaBaseConfiguration的功能,并在biz数据源/entityManager上定义了自己的PlatformTransactionManager.

So I tried to emulate what JpaBaseConfiguration does, defining my own PlatformTransactionManager over my biz datasource/entityManager.

    @Primary
    @Bean
    public PlatformTransactionManager appTransactionManager(final LocalContainerEntityManagerFactoryBean appEntityManager) {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(appEntityManager.getObject());
        this.appTransactionManager = transactionManager;
        return transactionManager;
    }

请注意,我必须用transactionManager以外的其他名称来定义它,否则Spring会发现2个bean并抱怨(与@Primary!无关)

Note I have to define it with a name other than transactionManager, otherwise Spring finds 2 beans and complains (unregardless of @Primary!)

但是现在有趣的部分来了.运行测试时,一切运行顺利,测试成功完成,并为业务数据库和Batch/Task's数据库正确创建了DDLs,数据库读取工作正常,但是业务数据未持久保存在我的测试数据库中,因此最终的assertThats在以下情况下失败:数数.如果我在测试PlatformTransactionManagerÈntityManager@Autowire,则所有内容均表明它们是正确的.但是,如果我在entityRepository.save中调试并执行org.springframework.transaction.interceptor.TransactionAspectSupport.currentTransactionStatus(),则似乎Batch's配置中的DatasourceTransactionManager被覆盖,因此未使用我的自定义暴露的PlatformTransactionManager.

But now it comes the funny part. When running the tests, everything runs smooth, tests finish and DDLs are properly created for both business and Batch/Task's databases, database reads work flawlessly, but business data is not persisted in my testing database, so final assertThats fail when counting. If I @Autowire in my test PlatformTransactionManager or ÈntityManager, everything indicates they are the proper ones. But if I debug within entityRepository.save, and execute org.springframework.transaction.interceptor.TransactionAspectSupport.currentTransactionStatus(), it seems the DatasourceTransactionManager from Batch's configuration is overriding, so my custom exposed PlatformTransactionManager is not being used.

所以我想我的PlatformManager是主要对象不是问题,但是正在配置JPA层TransactionInterceptor以使用非主要但transactionManager名为Batch的bean.

So I guess it is not a problem of my PlatformManager being the primary, but that something is configuring my JPA layer TransactionInterceptor to use the non primary but transactionManager named bean of Batch.

我也尝试过使@Configuration实现TransactionManagementConfigurer并覆盖PlatformTransactionManager annotationDrivenTransactionManager(),但还是没有运气

I also tried with making my @Configuration implement TransactionManagementConfigurer and override PlatformTransactionManager annotationDrivenTransactionManager() but still no luck

因此,我想问的是,是否有一种方法可以为JPA层配置主TransactionManager.

Thus, I guess what I am asking is whether there is a way to configure the primary TransactionManager for the JPA Layer.

推荐答案

当SimpleBatchConfiguration + DefaultBatchConfigurer公开PlatformTransactionManager bean时,就会出现问题,

The problem comes when SimpleBatchConfiguration+DefaultBatchConfigurer expose a PlatformTransactionManager bean,

正如您提到的,这确实是 BATCH-2788 中所报告的内容.我们正在研究的解决方案是仅在Spring Batch创建事务管理器bean时公开它.

As you mentioned, this is indeed what was reported in BATCH-2788. The solution we are exploring is to expose the transaction manager bean only if Spring Batch creates it.

同时,您可以设置属性spring.main.allow-bean-definition-overriding=true以允许Bean定义覆盖,并设置希望Spring Batch与BatchConfigurer#getTransactionManager一起使用的事务管理器.在您的情况下,它将类似于:

In the meantime you can set the property spring.main.allow-bean-definition-overriding=true to allow bean definition overriding and set the transaction manager you want Spring Batch to use with BatchConfigurer#getTransactionManager. In your case, it would be something like:

@Bean
public BatchConfigurer batchConfigurer() {
    return new DefaultBatchConfigurer(this.singletonNotExposedSpringDatasource()) {
        @Override
        public PlatformTransactionManager getTransactionManager() {
            return new MyTransactionManager();
        }
    };
}

希望这会有所帮助.

这篇关于需要配置我的JPA层以使用TransactionManager(Spring Cloud Task +批处理意外注册PlatformTransactionManager)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆