我们正在使用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" />
作业配置
<!-- 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>
下面是Spring批处理作业配置
<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>
这里我们定义了批处理:skippable-outtion-class,如果任何记录插入语句失败,应该使用它来处理。
举个例子,我们在 csv 文件中有 10 条记录,我们正在逐条读取并在 5 上插入到卡盘中的数据库表中,但在两者之间,比如说第 4 条记录插入失败,它应该继续第 5 条记录,并且应该只跳过第 4 条记录。
但是对于 batch:skippable-exception-classes,如果第 4 条记录失败,它将再次从第 1 条记录继续。所以在数据库表中我们有 1-3 条记录 2 次(重复记录)
请建议,如果我缺少Spring批次的任何配置属性。
这是在写入阶段发生异常时的标准行为。< br >
项目(从1到5)逐个写入,但作为单个块提交,如果发生错误,SB无法检测应跳过哪个项目,因此,SB如何决定应跳过哪些项目
SB再次开始写入阶段,但逐个写入项目(如设置提交间隔="1"
)以检测坏项目并将其发送到SkipListener.skipInWrite(item,异常)
。
使用选择/更新策略而不是简单的插入来写。
我认为,这项工作仍在进行中。请参阅此 JIRA 问题和此问题。它已经讨论了很长一段时间:Spring论坛帖子 1 和帖子 2。也许对两个JIRA问题进行一些额外的投票会使它们更加重要,更有可能被添加。
您配置事务管理器的方式有问题(未包含在上面的配置中)。虽然 bellabax 是正确的,因为当正在写入的项目引发异常时,整个块都会回滚,并且每个项目都会被单独处理/写入以确定块中的哪个项目导致了错误,但关键点似乎不适合你实际回滚。
UPDATEResourcelessTransactionManager
不是真正的事务管理器,不适用于事务资源(如数据库)。用真正的事务管理器配置你的工作,你会没事的。
我有以下步骤在批处理工作。 当某个异常抛出时,我在parseStepSkipListener中捕捉他并登录数据库。 我期待以下行为: 作业已启动 执行前面的步骤 开始执行解析步骤 阅读项目 进程项 写 哦,异常。 捕获异常,登录数据库,转到下一个块(读取、处理、写入)。 作业已启动 执行前面的步骤 开始执行解析步骤 阅读项目 进程项 写 哦,异常。 进程项 写入项 哦,异常。 捕获异常,登录数据库
const SKIP_NONE = 0x00; // 不忽略任何单元格、行 const SKIP_EMPTY_ROW = 0x01; // 忽略空行 const SKIP_EMPTY_CELLS = 0x02; // 忽略空单元格(肉眼观察单元格内无数据,并不代表单元格未定义、未使用) const SKIP_EMPTY_VALUE = 0X100; // 忽略单元格空数据
在我的spring boot应用程序中,我试图进行批插入以提高写入性能。问题是,我定期获得重复数据,对于这些数据,我的表上有一些唯一的约束。在进行串行插入时,我只捕获DataIntegrityException并忽略它们。但在执行批插入时,即使一次插入失败,也不会保存整个批。我希望hibernate仍然保存不会抛出错误的记录。我正在使用存储库。saveAll()用于插入,我的数据库是Mysql
问题内容: 众所周知,由于连接错误问题,我们无法从elasticsearch中获取超过10000行的python行。我想要从我的弹性簇中获取两个小时的数据,并且每5分钟要进行10000次观测。 1.)有什么方法可以将elasticsearch中的数据直接转储到csv或计数超过10000的某些Nosql数据库中。 我用python编写代码。 我正在使用Elasticsearch版本5 问题答案: 尝
本文向大家介绍如何读取CSV文件并将值存储到C#中的数组中?,包括了如何读取CSV文件并将值存储到C#中的数组中?的使用技巧和注意事项,需要的朋友参考一下 CSV文件是逗号分隔的文件,用于以有组织的方式存储数据。它通常以表格形式存储数据。大多数企业组织将其数据存储在CSV文件中。 CSV文件是逗号分隔的文件,用于以有组织的方式存储数据。它通常以表格形式存储数据。大多数企业组织将其数据存储在CSV文
问题内容: 例如,我在工作中有3个步骤(类似于Step1): 即使在步骤1中出现异常后,如何继续执行步骤2和3?我的意思是用Java配置。 问题答案: 这是创建流时如何配置它的示例。这应该与直接通过作业生成器进行配置类似:
请看下面这个数据文件的架构 > 问题1:我需要将第一列数据分成两列,这样整数数据应该在一列中,数组数据应该在另一列中。不确定如何在Spark/Scala中实现?任何关于这一点的指示都将是有帮助的。 当我试图将此数据文件写入csv文件时,我得到了以下错误
我是编程界的新手。嗯,我正在尝试使用ApachePOI库读取excel文件(5行5列)。我实际上有两个相同问题的实现。在第一个代码片段中,我只是读取excel文件并将其打印到控制台中。 然而,现在我正试图将读取的excel数据保存到一个数组中。所以我想在动态获取excel行和列大小后设置数组大小。但令我惊讶的是,当我执行第二个代码段时,似乎“while(cellIterator.hasNext()