Spring 具有两个数据源的引导批处理导致 javax.persistence.TransactionRequiredException:正在执行 update/delete 查询

Spring Boot Batch with two Datasources causes javax.persistence.TransactionRequiredException: Executing an update/delete query

我有一个包含两个数据源的 spring boot batch 项目,一个用于批处理表,一个用于业务表。它可以很好地读取业务数据库。

我的配置看起来像

@Configuration
@EnableBatchProcessing
public class DataSourceConfiguration {

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

    @Bean
    @ConfigurationProperties(prefix = "spring.sybasedatasource")
    public DataSource sybaseDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    BatchConfigurer batchConfigurer(DataSource dataSource) {
        return new DefaultBatchConfigurer(dataSource);
    }

    @Bean
    TaskConfigurer taskConfigurer(DataSource dataSource) {
        return new DefaultTaskConfigurer(dataSource);
    }
}

但是当我执行更新时

public interface DocumentRepository extends JpaRepository<DocumentDescriptor, Integer> {

    @Modifying
    @Query(value = "update document set process_status = :status where process_status = 10001 and document_id = :documentId")
    int updateDocumentStatus(Integer status, Integer documentId);
}

我得到一个 Caused by: org.springframework.dao.InvalidDataAccessApiUsageException: Executing an update/delete query; nested exception is javax.persistence.TransactionRequiredException: Executing an update/delete query

我已经查看了一些 Whosebug 问题并将 @Transactional 添加到存储库方法中。此外,我创建了专门的 TransactionManager

@Bean(name="tm1")
public PlatformTransactionManager tm1(@Qualifier ("dataSource") DataSource datasource) {
    return new DataSourceTransactionManager(datasource);
}

@Bean(name="tm2")
public PlatformTransactionManager tm2(@Qualifier ("sybaseDataSource") DataSource datasource) 
{
    return new DataSourceTransactionManager(datasource);
}

并使用了@Transaction("tm2"),但例外情况仍然相同。

知道如何才能获得正确的交易吗?

我用

解决了
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
    basePackages = 
"...",
    entityManagerFactoryRef = "sybaseEntityManagerFactory",
    transactionManagerRef = "sybaseTransactionManager"
)
public class DataSourceConfiguration {

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

@Bean
@ConfigurationProperties(prefix = "spring.sybasedatasource")
public DataSource sybaseDataSource() {
    return DataSourceBuilder.create().build();
}

@Bean
public LocalContainerEntityManagerFactoryBean sybaseEntityManagerFactory() {
    return new EntityManagerFactoryBuilder(new HibernateJpaVendorAdapter(), Collections.emptyMap(), null)
            .dataSource(sybaseDataSource())
            .packages("...")
            .persistenceUnit(DataSourceConfiguration.class.getSimpleName())
            .build();
}

@Bean
@Primary
public DataSourceTransactionManager postgresTransactionManager(@Qualifier("dataSource") DataSource datasource) {
    return new DataSourceTransactionManager(datasource);
}

@Bean
public JpaTransactionManager sybaseTransactionManager(EntityManagerFactory entityManagerFactory) {
    return new JpaTransactionManager(entityManagerFactory);
}
}

@Transactional("sybaseTransactionManager")