Spring Batch Processor没有看到更新的数据

时间:2017-08-16 06:01:50

标签: java spring spring-batch

我正在使用Spring Batch 3.0.7,EclipseLink 2.6.4和Oracle 11/12。

我在数据库中有一对多的关系。批处理读取器读取处理器读取多方(子)的一侧(父级)。 我确信它们都是由不同的应用程序以事务方式插入的。

批量阅读器派生自JdbcCursorItemReader,只需设置rowMapperpreparedStatementSetter

处理器是使用Spring Data JpaRepository的ItemProcessor,并将数据添加到父级。 存储库有@Transactional(readOnly = true)

读者似乎始终使用相同的数据库会话,并且处理器始终使用不同的数据库会话。

通过此设置,我不时会遇到ORA-01555(快照太旧)错误。 但是甚至有一个更大的问题: 如果作业运行之间有新的父子数据,则读者会找到父级,但处理器看不到任何子级。 只有第一个父/子插入工作(以某种方式处理器保留在Oracle数据的修复快照上)。

我为解决这个问题做了些什么: 在每个作业运行中,我关闭Spring Context然后重新创建它。 这解决了两个问题(ORA-01555错误,并且没有看到处理器更新的数据。)

重新创建Spring Context的目的是获得一个新的数据库会话。我不知道这样做的方法比较简单。

我认为没有必要重新创建Context但我找不到这种行为的原因。

更新 在这里,您可以找到代码的骨架 https://github.com/th-e/SpringBatchDataPump

1 个答案:

答案 0 :(得分:0)

您需要了解该事务包装read-process-write序列。因此,如果之间发生其他一些数据库写入 - 此事务将失败。

  

读者似乎总是使用相同的数据库会话和   处理器总是使用不同的数据库会话。

这是一个奇怪的陈述,如果您确定这是真的,那么您必须再次检查您的配置。情况应该不是这样。

您可以检查您的交易属性。

    <batch:tasklet>
      <batch:transaction-attributes isolation="READ_COMMITTED" propagation="REQUIRES_NEW" timeout="200"/>
      <batch:chunk reader="myItemReader" writer="myItemWriter" commit-interval="20"/>
    </batch:tasklet>

例如,如果您不介意脏读 - 您可以将隔离更改为READ_UNCOMMITTED

另一种解决方案:您可以配置弹簧批提供的重试机制:

<batch:tasklet>
  <batch:chunk reader="myItemReader" writer="myItemWriter" commit-interval="20" retry-limit="15">
    <batch:retryable-exception-classes>
       <batch:include class="com.stackoverflow.MyRetryableException" />
    </batch:retryable-exception-classes>
  </batch:chunk>
</batch:tasklet>