5

我有一个简单的 Spring-Service(在其他任务中)使用以下代码启动一个 spring 批处理作业:

@Autowired
private JobRegistry jobRegistry;

@Autowired
private JobLauncher jobLauncher;

public void startMyJob() {
    Job job = jobRegistry.getJob("myJobName");
    JobParameters jobParameters = new JobParametersBuilder().toJobParameters();
    jobLauncher.run(job, jobParameters);
}

只要调用 Serivce-Method 时没有活动的事务,这就可以正常工作。但是,通过活动交易,我得到了这个异常:

Caused by: java.lang.IllegalStateException: Existing transaction detected in JobRepository. Please fix this and try again (e.g. remove @Transactional annotations from client).

我不能轻易删除现有事务,因为它是由于某些框架代码不在我范围内而隐含的。

那么,在这种情况下,我该如何开始工作呢?新工作不应该使用现有事务。它可以开始自己的事务——但是如何配置它以使其工作?

4

4 回答 4

6

我有一个类似的问题。特别是,我从一个带有注释的类中开始我的工作@Transactional(propagation = Propagation.REQUIRES_NEW)。为了解决这个问题,我从一个没有活动交易的地方开始工作。然后我遇到了如上所述的问题 - 这是我解决它的方法:

在 JobRepository 上设置validateTransactionState为 false - 它现在忽略了在我调用的类中自动创建的事务ItemProcessor(因为如上所述,该类使用 @Transcational 进行了注释)。

这使我的工作运行良好。但是,我不确定我现在是否正在处理 2 笔未结交易,并且想确定我不是。因此,我还删除了类级别的跨类注解,并将其移至所有公共方法,但我的 Itemprocessor 调用的方法除外。因此我解决了这个问题。

于 2015-02-19T14:02:27.250 回答
5

我的解决方案是,启动作业的方法需要使用 this 进行注释,@Transactional(propagation = Propagation.NOT_SUPPORTED)这将暂停当前事务并在执行后恢复。

如果您需要与默认值不同的任何内容,您可以设置transactionAttribute您的读者和作者。

我不需要setValidateTransactionState(false)JobRepositoryFactoryBeanJobRepository

于 2017-10-03T13:47:14.920 回答
3

我通过创建一个单独的 bean AsyncJobLauncher 来解决这个问题,它有一个与 JobLauncher 具有相同签名的 run 方法并委托给真实的,但用 Spring 的 @Async 标记。因此,作业的启动发生在一个新线程的后台,所以它在它自己的事务中。

于 2014-08-01T17:08:36.000 回答
2

使用AbstractJobRepositoryFactoryBean.ValidateTransactionState,但要小心使用(警告:前方有龙)。

SimpleJobLauncher.executor要使用另一个事务,您可以使用标记为 @Transactional()的方法注入自定义Executor.run(或创建自定义JobLauncher并在方法上执行相同的技巧run)。

我没有尝试过,因为我没有遇到过这个问题,但希望可以提供帮助。

于 2013-08-08T12:49:39.437 回答