【问题标题】:How to manage shorter transaction inside Spring Batch chunk?如何在 Spring Batch 块中管理较短的事务?
【发布时间】:2018-02-24 13:01:45
【问题描述】:

我在使用 Spring Batch 时遇到问题,似乎找不到解决方案。

所以,我已经批量处理了一些项目(大小 10)。我还有一个事务管理器被这个批次用来在每个块之后持久化处理过的项目。

但是...我还想实时保留这些项目的一些进度状态。所以在处理一个项目之前,我想保存一个状态,说明这个项目正在进行中。

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

  1. 如果我只是用 Transactional 注释来注释我的状态管理器服务,则状态将在整个块处理之后提交。
  2. 如果我将 REQUIRES_NEW 作为传播级别添加到注释,它可以工作...但是批处理以某种死锁结束(我读到这是 REQUIRES_NEW 的常见问题强>)。
  3. 所以我最后的猜测是添加第二个事务管理器(在同一个数据源上)并在状态管理器服务上使用它...但我得到了与解决方案 #1 相同的结果(这对我来说似乎很奇怪,正如我所料来自此管理器的事务独立于块事务执行)。

有人遇到过这个问题吗?

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

类 DbConfiguration:

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

类作业配置:

@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;
    }
}

类 StatusManagerServiceImpl:

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

【问题讨论】:

  • 我不希望 1 或 2 能够工作,原因您可以在 StackOverflow 的其他地方找到。你能提供 3 的配置吗?
  • 嗨,迈克尔!我刚刚添加了我的配置,简化以专注于问题。我希望它就足够了。
  • 谁造成了StatusManagerService
  • 此服务在多种情况下被调用: - 进程开始时 - 读取器、处理器或写入器失败时 - 步骤结束时
  • 全部来自听众?

标签: java spring transactions spring-batch


【解决方案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.
            }
        });
    }
}

如果您有要返回的结果,您也可以使用 new TransactionCallback。然后执行方法将返回该结果。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-12-01
    • 2015-05-31
    • 2021-02-07
    • 2013-07-30
    • 2021-02-20
    • 2019-01-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多