我正在使用Spring Batch和JPA,并且我经历了TransactionManager bean冲突。我通过在一个步骤中将TransactionManager设置为JpaTransactionManager找到了一个解决方案。但根据这个链接(https://github.com/spring-projects/spring-batch/issues/961),这是不正确的,即使它适用于我。
@Autowired
private JpaTransactionManager transactionManager;
private Step buildTaskletStep() {
return stepBuilderFactory.get("SendCampaignStep")
.<UserAccount, UserAccount>chunk(pushServiceConfiguration.getCampaignBatchSize())
.reader(userAccountItemReader)
.processor(userAccountItemProcessor)
.writer(userAccountItemWriter)
.transactionManager(transactionManager)
.build();
}
}
我尝试了实现batchconfigiler的建议解决方案,但它与我使用以下代码禁用元数据表相冲突:
@Configuration
@EnableAutoConfiguration
@EnableBatchProcessing
public class BatchConfiguration extends DefaultBatchConfigurer {
@Override
public void setDataSource(DataSource dataSource) {
// override to do not set datasource even if a datasource exist.
// initialize will use a Map based JobRepository (instead of database)
}
}
使用在步骤中设置TransactionManager的第一种解决方案会有什么问题?
在Spring Batch中,有两个地方使用事务管理器:
- 在
JobRepository
周围创建的代理中,在与作业存储库交互时创建事务方法 - 在每个步骤定义中驱动步骤的事务
通常,在两个地方使用相同的事务管理器,但这不是必需的。在作业存储库中使用ResourcelessTransactionManager
来不存储任何元数据,在步骤中使用JpaTransactionManager
来将数据持久化到数据库中,这是完全可以的。
默认情况下,当您使用@EnableBatchProcessing
并提供DataSource
bean时,Spring Batch将创建DataSourceTransactionManager
并在两个位置设置它,因为这是最典型的情况。但是没有什么可以阻止您为该步骤使用不同的事务管理器。在这种情况下,您应该接受当出现问题时业务数据和技术元数据可能不同步的事实。
这就是为什么提供自定义事务管理器的预期方式是通过自定义BatchConfigurer#getTransactionManager
,在这种情况下,您的自定义事务管理器在两个地方都设置了它。这个问题没有明确的文档记录,但自v4.1以来已经修复了。下面是提到这一点的部分:配置jobrerepository。@EnableBatchProcessing:
In order to use a custom transaction manager, a custom BatchConfigurer should be provided.