Spring Batch - 读取csv并使用跳过/异常策略将数据转储到表中

时间:2014-05-14 10:43:16

标签: spring spring-batch

我们正在使用Spring Batch从CSV文件中读取记录并插入到数据库表中。

数据源和事务管理器

<!-- connect to database -->
    <bean id="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="oracle.jdbc.OracleDriver" />
        <property name="url" value="**********" />
        <property name="username" value="**********" />
        <property name="password" value="**********" />
    </bean>

    <bean id="transactionManagerTest"
        class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />

JOB配置

<!-- stored job-meta in database -->
    <bean id="jobRepository"
        class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="transactionManager" ref="transactionManagerTest"  />
        <property name="databaseType" value="Oracle" />
    </bean>


<bean id="jobLauncher"
        class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
        <property name="jobRepository" ref="jobRepository" />
        <property name="taskExecutor"> 
        <bean class="org.springframework.core.task.SimpleAsyncTaskExecutor" />
          </property> 
    </bean>

以下是春季批量作业配置

<batch:job id="reportJob">
        <batch:step id="step1" >
            <batch:tasklet transaction-manager="transactionManagerTest" >
                <batch:chunk reader="cvsFileItemReader" writer="mysqlItemWriter" commit-interval="5" skip-limit="1000" processor-transactional="true">

                    <!-- 
                     <batch:skip-policy>
                        <bean class="org.springframework.batch.core.step.skip.AlwaysSkipItemSkipPolicy" scope="step"/>
                    </batch:skip-policy> -->
                    <batch:skippable-exception-classes>
                        <batch:include class="java.lang.Exception" />
                    </batch:skippable-exception-classes>
                    <!-- <batch:retry-policy>
                        <bean class="org.springframework.retry.policy.NeverRetryPolicy" scope="step"/>
                    </batch:retry-policy> -->
                    <batch:listeners>
                         <batch:listener ref="itemWriterListner"/>
                    </batch:listeners>
                </batch:chunk>
            </batch:tasklet>
        </batch:step>
    </batch:job>

这里我们定义了 batch:skippable-exception-classes ,如果任何记录插入语句失败,应该用它来处理。

举一个例子,我们在csv文件中有10条记录,我们正逐一读取并插入数据库表中的chuck on 5,但在介于两者之间,说第4条记录插入失败,它应该继续第5条记录以后,应该只跳过第4条记录。

但是对于 batch:skippable-exception-classes ,如果第4条记录失败,它将再次从第1条记录继续。所以在数据库表中我们有1-3次记录(重复记录)

请提示,如果我遗漏了春季批次的任何配置属性。

4 个答案:

答案 0 :(得分:6)

您配置交易管理器的方式有问题(上面的配置中没有包含这些内容)。虽然bellabax是正确的,因为当正在写入的项目抛出异常时,整个块被回滚并且每个项目被单独处理/写入以确定块中的哪个项目导致错误,这个关键点似乎不会出现为你工作的是实际回滚。

<强>更新 ResourcelessTransactionManager不是真正的事务管理器,不适用于事务资源(如数据库)。使用真实的交易管理器配置您的工作,您就可以了。

答案 1 :(得分:2)

我相信这仍然是一项正在进行中的工作。见JIRA issuethis one。 现在已经讨论了很长一段时间:春季论坛post 1post 2。也许对两个JIRA问题进行一些额外投票会使它们变得更加重要并且更有可能被添加。

答案 2 :(得分:2)

这是在写作阶段发生异常时的标准行为。

项目(从1到5)是逐个写入但作为单个块提交,如果发生错误,SB无法检测应跳过哪个项目,SB如何决定哪个项目(s )应该被跳过?

SB再次开始写入阶段,但逐项写入项目(设置commit-interval="1")以检测错误项目并将其发送到SkipListener.skipInWrite(item,exception)

关于项目重复使用SELECT / UPDATE策略而不是简单的INSERT写入。

答案 3 :(得分:1)

将事务管理器定义如下

 <bean id="transactionManager"
            class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
             <property name="dataSource" ref="dataSource"/>
    </bean>

这应该可以解决问题。