You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Batch后续步骤如何读取前置步骤更新的表数据?

Spring Batch多Step数据更新异常排查与解决

问题场景

创建包含两个Step的Spring Batch Job:

  • Step1:读取Oracle表中含特定字符的条目,更新移除该字符
  • Step2:读取上述Oracle表的更新后数据,迁移至Sybase数据库
    测试发现Step2始终读取Step1更新前的数据,排查后发现两个核心问题:事务管理器配置不匹配、更新SQL语句错误。

初始Job配置

<job id="example-job" job-repository="jobRepository" xmlns="http://www.springframework.org/schema/batch">           
    <step id="update_table" parent="simpleStep" next="use_updated_data"> <!-- step 1 -->
        <tasklet>
            <chunk writer="updateTableItemWriter" reader="updateTableItemReader" commit-interval="100"/>
        </tasklet>            
    </step>
    <step id="use_updated_data" parent="simpleStep"> <!-- step 2 -->
        <tasklet>
            <chunk writer="useUpdatedTableItemWriter" reader="useUpdatedTableItemReader" commit-interval="100"/>
        </tasklet>            
    </step>
</job>

读写组件与Step父类配置

<beans:bean name="updateTableItemReader" scope="step" class="org.springframework.batch.item.database.JdbcCursorItemReader">
    <beans:property name="dataSource" ref="oracleDS" />
    <beans:property name="sql" value="${read.findEntriesWithChar}">
    </beans:property>
    <beans:property name="rowMapper">
        <beans:bean name="mapper" class="com.myProj.batch.tableRowMapper" />
    </beans:property>
</beans:bean>    

<beans:bean  id="updateTableItemWriter" class="org.springframework.batch.item.database.JdbcBatchItemWriter">
    <beans:property name="assertUpdates" value="false" />
    <beans:property name="itemSqlParameterSourceProvider">
        <beans:bean name="sqlParameterSourceProvider" class="org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider" />
    </beans:property>
    <beans:property name="sql" value="${write.updateEntriesReplaceChar}"/>  
    <beans:property name="dataSource" ref="oracleDS" />
</beans:bean>

<beans:bean name="useUpdatedTableItemReader" scope="step" class="org.springframework.batch.item.database.JdbcCursorItemReader">
    <beans:property name="dataSource" ref="oracleDS" />
    <beans:property name="sql" value="${read.useUpdatedTableNoChar}">
    </beans:property>
    <beans:property name="rowMapper">
        <beans:bean name="mapper" class="com.myProj.batch.tableRowMapper" />
    </beans:property>
</beans:bean>    

<beans:bean  id="useUpdatedTableItemWriter" class="org.springframework.batch.item.database.JdbcBatchItemWriter">
    <beans:property name="assertUpdates" value="false" />
    <beans:property name="itemSqlParameterSourceProvider">
        <beans:bean name="sqlParameterSourceProvider" class="org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider" />
    </beans:property>
    <beans:property name="sql" value="${write.useUpdatedTableNoCharTransfer}"/>  
    <beans:property name="dataSource" ref="sybaseDS" />
</beans:bean>

<beans:bean id="simpleStep" class="org.springframework.batch.core.step.item.SimpleStepFactoryBean" abstract="true">
    <beans:property name="transactionManager" ref="transMan_sybase" />
    <beans:property name="jobRepository" ref="jobRepository" />
    <beans:property name="startLimit" value="100" />
    <beans:property name="commitInterval" value="1" />
</beans:bean>

核心问题与解决方案

1. 事务管理器与数据源不匹配

Step1操作Oracle数据库,但继承的simpleStep使用了Sybase的事务管理器transMan_sybase,导致Step1的事务无法正确提交至Oracle,数据更新未持久化。

修正方案:

  • 为Oracle单独配置事务管理器:
<beans:bean id="transMan_oracle" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <beans:property name="dataSource" ref="oracleDS" />
</beans:bean>
  • 拆分抽象Step,分别对应Oracle和Sybase:
<!-- Oracle操作的抽象Step -->
<beans:bean id="oracleSimpleStep" class="org.springframework.batch.core.step.item.SimpleStepFactoryBean" abstract="true">
    <beans:property name="transactionManager" ref="transMan_oracle" />
    <beans:property name="jobRepository" ref="jobRepository" />
    <beans:property name="startLimit" value="100" />
    <beans:property name="commitInterval" value="1" />
</beans:bean>

<!-- Sybase操作的抽象Step -->
<beans:bean id="sybaseSimpleStep" class="org.springframework.batch.core.step.item.SimpleStepFactoryBean" abstract="true">
    <beans:property name="transactionManager" ref="transMan_sybase" />
    <beans:property name="jobRepository" ref="jobRepository" />
    <beans:property name="startLimit" value="100" />
    <beans:property name="commitInterval" value="1" />
</beans:bean>
  • 修改Job中Step的父类:
<step id="update_table" parent="oracleSimpleStep" next="use_updated_data"> <!-- 使用Oracle事务管理器 -->
<step id="use_updated_data" parent="sybaseSimpleStep"> <!-- 使用Sybase事务管理器 -->

2. 更新SQL语句错误

原.properties中的更新SQL因关键字未转义导致执行失败:

-- 原错误SQL
SET desc = replace(desc, UNISTR('\2013'), '-') WHERE desc like '%' || UNISTR('\2013') || '%'

修正方案:
Oracle中desc是排序关键字,作为列名必须用英文双引号包裹;UNISTR的\2013写法符合U+2013字符的编码规则,修正后的SQL:

SET "desc" = replace("desc", UNISTR('\2013'), '-') WHERE "desc" like '%' || UNISTR('\2013') || '%'

若在.properties文件中配置,需注意双引号的转义规则,可直接使用"desc"或转义为\"desc\"。


内容的提问来源于stack exchange,提问作者Vincere

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 07:05:55