如何在Spring Batch块中管理更短的事务?

时间:2017-09-15 10:50:30

标签: java spring transactions spring-batch

我使用Spring Batch时遇到了问题,似乎无法找到解决方案。

所以,我已经批量处理了一些块(10号)。我还有一个事务管理器,用于在每个块之后保留已处理的项目。

但是......我还希望能够实时保持这些项目的某些进度状态。因此,在处理项目之前,我想保存一个状态,说明此项目正在进行中。

我似乎无法找到实现这一目标的解决方案。我尝试了以下解决方案:

  1. 如果我只是使用 Transactional 注释来注释我的状态管理器服务,则会在整个块处理之后提交状态。
  2. 如果我将 REQUIRES_NEW 作为传播级别添加到注释中,它可以工作......但批处理会以某种死锁结束(我读到这是 REQUIRES_NEW的常见问题)。
  3. 所以我最后的猜测是添加第二个事务管理器(在同一个数据源上)并在状态管理器服务上使用它......但是我得到了与解决方案#1相同的结果(这对我来说似乎很像我的预期该经理的交易独立于大块交易行事。)
  4. 有没有人遇到过这个问题?

    编辑: 这是我的配置,故意简化:

    DbConfiguration类:

    @Configuration
    public class DbConfiguration {
        @Bean
        @Primary
        public JpaTransactionManager transactionManager() throws Exception {
            final JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();
            jpaTransactionManager.setEntityManagerFactory(entityManagerFactory());
            jpaTransactionManager.afterPropertiesSet();
            return jpaTransactionManager;
        }
    }
    

    类JobConfiguration:

    @Configuration
    @Import(DbConfiguration.class)
    @EnableTransactionManagement
    public class JobConfiguration {
        @Autowired
        private EntityManagerFactory entityManagerFactory;
    
        @Bean
        public Job jobDefinition() {
            return jobBuilderFactory
                .get(JOB_NAME)
                .start(step())
                .build();
        }
    
        @Bean
        public Step step() {
            return stepBuilderFactory
                .get(STEP_NAME)
                .<Object, Object>chunk(COMMIT_INTERVAL)
                        .reader(reader())
                        .processor(processor())
                        .writer(writer())
                .build();
        }
    
        @Bean
        public PlatformTransactionManager statusTransactionManager() {
            final JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();
            jpaTransactionManager.setEntityManagerFactory(entityManagerFactory);
            jpaTransactionManager.afterPropertiesSet();
            return jpaTransactionManager;
        }
    }
    

    Class StatusManagerServiceImpl:

    @Transactional("statusTransactionManager")
    public class StatusManagerServiceImpl implements StatusManagerService {
        ...
    }
    

1 个答案:

答案 0 :(得分:1)

实现此目的的一种方法是使用Spring TransactionTemplate,如下所示:

@Service
public class StatusManagerServiceImpl implements StatusManagerService {
    @Autowired
    private PlatformTransactionManager transactionManager;

    public separateTransactionMethod() {
        TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                // Do something here that will be committed right away.
            }
        });
    }
}

如果有结果返回,您也可以使用新的TransactionCallback。然后execute方法将返回该结果。