当前位置: 首页 > 知识库问答 >
问题:

使Spring Batch ItemReader可重启

壤驷深
2023-03-14

我正在开发的spring批处理程序正在从表中读取数据。它使用的是“组织”。springframework。一批项目数据库JdbcCursorItemReader的itemReader。早些时候,计划是修改表,添加一个已处理的_指示符标志,并将其预填充为状态“待定”。一旦记录被处理,writer将把已处理的_指示器标志的状态更新为“已处理”。这是为了支持重新启动。例如,如果批次拾取了100万条记录,并在½万条记录中死亡,那么当我重新启动批次时;应该从我结束的地方开始。但不幸的是,管理层没有批准这个解决方案。我正在想方设法让itemreader重新启动。根据Spring文档,“大多数ItemReader都有更复杂的重启逻辑。例如,JdbcCursorItemReader将最后处理的行的行id存储在游标中。”

有人有这样的自定义阅读器的示例,它实现了JdbcCursorItemReader并将最后处理的行存储在光标中。https://docs.spring.io/spring-batch/trunk/reference/html/readersAndWriters.html

==完整的XML配置==

<import resource="classpath:/batch/utility/skip/batch_skip.xml" />
<import resource="classpath:/batch/config/context-postgres.xml" />
<import resource="classpath:/batch/config/oracle-database.xml" />

<context:property-placeholder
    location="classpath:/batch/jobs/TPF-1001-DD-01/TPF-1001-DD-01.properties" />
<bean id="gridSizePartitioner"
    class="com.tpf.partitioner.GridSizePartitioner" />

      <task:executor id="taskExecutor" pool-size="${pool.size}" />
<batch:job id="XYZJob" job-repository="jobRepository"
    restartable="true">

    <batch:step id="XYZSTEP">
        <batch:description>Convert TIF files to PDF</batch:description>
        <batch:partition partitioner="gridSizePartitioner">

            <batch:handler task-executor="taskExecutor"
                grid-size="${pool.size}" />
            <batch:step>
                <batch:tasklet allow-start-if-complete="true">
                    <batch:chunk commit-interval="${commit.interval}"
                        skip-limit="${job.skip.limit}">

                        <batch:reader>
                            <bean id="timeReader"
                                class="org.springframework.batch.item.database.JdbcCursorItemReader"
                                scope="step">
                                <property name="dataSource" ref="oracledataSource" />
                                <property name="sql">
                                    <value>                                     
                                    select TIME_ID as timesheetId,count(*),max(CREATION_DATETIME) as creationDateTime , ILN_NUMBER as ilnNumber
                                    from TS_FAKE_NAME
                                    where creation_datetime  >= '#{jobParameters['creation_start_date1']} 12.00.00.000000000 AM' 
                                    and creation_datetime &lt;  '#{jobParameters['creation_start_date2']} 11.59.59.999999999 PM' 
                                    and mod(time_id,${pool.size})=#{stepExecutionContext['partition.id']} 
                                    group by  time_id ,ILN_NUMBER                                   

                                    </value>
                                </property>
                                <property name="rowMapper">
                                    <bean
                                        class="org.springframework.jdbc.core.BeanPropertyRowMapper">
                                        <property name="mappedClass"
                                            value="com.tpf.model.Time" />
                                    </bean>
                                </property>
                            </bean>
                        </batch:reader>
                        <batch:processor>
                            <bean id="compositeItemProcessor"
                                class="org.springframework.batch.item.support.CompositeItemProcessor">
                                <property name="delegates">
                                    <list>
                                        <ref bean="timeProcessor" />
                                    </list>
                                </property>

                            </bean>
                        </batch:processor>


                        <batch:writer>
                            <bean id="compositeItemWriter"
                                class="org.springframework.batch.item.support.CompositeItemWriter">
                                <property name="delegates">
                                    <list>
                                        <ref bean="timeWriter" />
                                    </list>
                                </property>
                            </bean>
                        </batch:writer>
                        <batch:skippable-exception-classes>
                            <batch:include
                                class="com.utility.skip.BatchSkipException" />
                        </batch:skippable-exception-classes>
                        <batch:listeners>
                            <batch:listener ref="batchSkipListener" />
                        </batch:listeners>
                    </batch:chunk>
                </batch:tasklet>
            </batch:step>
        </batch:partition>
    </batch:step>
    <batch:validator>
        <bean
            class="org.springframework.batch.core.job.DefaultJobParametersValidator">
            <property name="requiredKeys">
                <list>
                    <value>batchRunNumber</value>
                    <value>creation_start_date1</value>
                    <value>creation_start_date2</value>
                </list>
            </property>
        </bean>
    </batch:validator>
</batch:job>



<bean id="timesheetWriter" class="com.tpf.writer.TimeWriter"
    scope="step">
    <property name="dataSource" ref="dataSource" />
</bean>

<bean id="timeProcessor"
    class="com.tpf.processor.TimeProcessor" scope="step">
    <property name="dataSource" ref="oracledataSource" />
</bean> 

共有1个答案

养枫涟
2023-03-14

有没有人有这样的定制阅读器的示例,它实现了JdbcCursorItemReader,并在游标中存储最后处理的行

JdbcCursorItemReader可以做到这一点,参见Javadoc,这里是一个摘录:

ExecutionContext: The current row is returned as restart data,
and when restored from that same data, the cursor is opened and the current row
set to the value within the restart data.

所以你不需要定制阅读器。

 类似资料:
  • 问题内容: 该代码无法编译,编译器说f含糊。但是我认为第二种方法可以解决什么问题? 问题答案: 这是因为无法确定该方法调用是应调用变量args还是应调用float和变量args。 Java决定以这种方式来调用拓宽>装箱>变量args的方法,但是在这种情况下,两者都具有变量args。 在这种情况下,基本上将char扩展为浮动。 Java基元的扩展顺序为:

  • 我想要一个Java中不可更改的ArrayList。所以你不能删除或添加任何元素。所以所有的工作都是由构造器完成的。 到目前为止,我已经试着用下面的方法使列表最终确定 <代码>公共静态最终列表 这不起作用,因为您仍然可以在其中添加元素。 接下来,我在网上搜索并发现您可以像这样覆盖所有方法: 这对我来说似乎不是一个好的解决方案,因为我需要为这么简单的事情投入大量的工作。 有没有一种简单的方法可以制作一

  • 问题内容: 在我的测试中,创建者不尊重EXIF标头。 例如,当设备拍摄的肖像图像不会根据相机的方向旋转实际的像素数据,而是将其存储在EXIF标头中时,当我调用和时,它们将返回错误的值(宽度的高度,反之亦然)。 有没有办法 尊重EXIF并产生正确的答案? 如果没有,建议使用哪种模式来处理此问题? 没有经验丰富的Android开发人员的建议,我看到的唯一方法是对拍摄的图像进行预处理(加载,根据EXIF

  • 我正在制作一个网站,我认为导航栏会导致较小的设备太大。我发现了如何使它可滚动,但我不喜欢它旁边显示一个新的滚动条。我怎样才能让它隐形?

  • Swagger2.0支持可重用参数,如下所述。 如何使用Springfox利用此特性 SpringFox支持这个特性吗?

  • 我需要将每个请求的不同系统属性设置为REST API。可以使用