需要配置我的JPA层以使用TransactionManager(Spring Cloud Task +批处理意外注册PlatformTransactionManager) [英] Need to configure my JPA layer to use a TransactionManager (Spring Cloud Task + Batch register a PlatformTransactionManager unexpectedly)
问题描述
我在项目中使用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时出现问题,因为JpaBaseConfiguration
在PlatformTransactionManager
上具有@ConditionalOnMissingBean
.因此,绑定到spring.datasource
的Batch'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屋!