Controlling Rollback

默认情况下,无论重试或跳过,从 ItemWriter 引发的任何异常都会导致由 Step 控制的交易回滚。如果按照前面所述配置跳过,则从 ItemReader 引发的异常不会导致回滚。然而,存在许多场景,在这种场景中,从 ItemWriter 引发的异常不应导致回滚,因为没有发生任何导致交易失效的操作。因此,您可以使用不应导致回滚的异常列表配置 Step

By default, regardless of retry or skip, any exceptions thrown from the ItemWriter cause the transaction controlled by the Step to rollback. If skip is configured as described earlier, exceptions thrown from the ItemReader do not cause a rollback. However, there are many scenarios in which exceptions thrown from the ItemWriter should not cause a rollback, because no action has taken place to invalidate the transaction. For this reason, you can configure the Step with a list of exceptions that should not cause rollback.

Java

在 Java 中,您可以按如下方式控制回滚:

In Java, you can control rollback as follows:

Java Configuration
@Bean
public Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
	return new StepBuilder("step1", jobRepository)
				.<String, String>chunk(2, transactionManager)
				.reader(itemReader())
				.writer(itemWriter())
				.faultTolerant()
				.noRollback(ValidationException.class)
				.build();
}
XML

在 XML 中,您可以按如下方式控制回滚:

In XML, you can control rollback as follows:

XML Configuration
<step id="step1">
   <tasklet>
      <chunk reader="itemReader" writer="itemWriter" commit-interval="2"/>
      <no-rollback-exception-classes>
         <include class="org.springframework.batch.item.validator.ValidationException"/>
      </no-rollback-exception-classes>
   </tasklet>
</step>

Transactional Readers

ItemReader 的基本契约是它仅进不退。该步骤缓冲了读取输入,因此在回滚的情况下,无需从读取器重新读取项目。然而,存在某些场景,在这种场景中,读取器是建立在交易资源之上,例如 JMS 队列。在此情况下,由于队列已绑定到已回滚的交易,因此从队列中提取的消息将被放回去。出于此原因,您可以配置该步骤以不缓冲项目。

The basic contract of the ItemReader is that it is forward-only. The step buffers reader input so that, in case of a rollback, the items do not need to be re-read from the reader. However, there are certain scenarios in which the reader is built on top of a transactional resource, such as a JMS queue. In this case, since the queue is tied to the transaction that is rolled back, the messages that have been pulled from the queue are put back on. For this reason, you can configure the step to not buffer the items.

Java

以下示例展示了如何在 Java 中创建一个不缓冲项目的读取器:

The following example shows how to create a reader that does not buffer items in Java:

Java Configuration
@Bean
public Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
	return new StepBuilder("step1", jobRepository)
				.<String, String>chunk(2, transactionManager)
				.reader(itemReader())
				.writer(itemWriter())
				.readerIsTransactionalQueue()
				.build();
}
XML

以下示例展示了如何在 XML 中创建一个不缓冲项目的读取器:

The following example shows how to create a reader that does not buffer items in XML:

XML Configuration
<step id="step1">
    <tasklet>
        <chunk reader="itemReader" writer="itemWriter" commit-interval="2"
               is-reader-transactional-queue="true"/>
    </tasklet>
</step>