我正在尝试使用预准备语句将记录插入postgres表,但是在使用insert语句时我遇到了以下错误:
[main] ERROR org.springframework.batch.core.step.AbstractStep - Encountered an error executing step someStep in job someJob
org.springframework.dao.EmptyResultDataAccessException: Item 0 of 1 did not update any rows: [[com.abc.abc.abc.dao.orm.SomeORM@6653en,com.abc.abc.abc.dao.orm.SomeORM@75f04e]
at org.springframework.batch.item.database.JdbcBatchItemWriter.write(JdbcBatchItemWriter.java:202)
我的作者是:
package com.somepackage.writer;
public class trialClass implements ItemPreparedStatementSetter<List<someORM>> {
@Override
public void setValues(List<someORM> itemList,java.sql.PreparedStatement ps) throws SQLException,EmptyResultDataAccessException {
try {
for (ORM item : itemList) {
for (int i = 0;i<itemList.size();i++)
{
ps.setInt(1, itemList.get(i).getPropOne());
ps.setString(2, itemList.get(i).getPropTwo());
ps.setInt(3, itemList.get(i).getPropThree());
ps.setInt(4, itemList.get(i).getPropFour());
ps.addBatch();
}
int[] rs = ps.executeBatch();
} catch (Exception e) {
e.printStackTrace();
}}}
我的xml文件是这样的:
<beans:bean id="beanId" scope="step"
class="org.springframework.batch.item.support.CompositeItemWriter">
<beans:property name = "delegates">
<util:list>
<beans:ref bean= "someId"/>
<beans:ref bean= "someOtherId"/>
</util:list>
</beans:property>
</beans:bean>
<beans:bean id = "someId" scope = "step"
class="org.springframework.batch.item.database.JdbcBatchItemWriter">
<beans:property name="dataSource" ref="someSource" />
<beans:property name="sql" value = "${fetch.somequery.sql}" >
</beans:property>
<beans:property name="itemPreparedStatementSetter" ref="someRef" />
</beans:bean>
我在插入记录时只收到错误,更新工作正常 (postgres表在第一列上有主键) (在两种情况下,记录都在postgres表中插入/更新,但在插入的情况下仍会出现此错误)
我正在使用查询:
fetch.somequery.sql =INSERT INTO table1 (col1, col2, col3) SELECT ?,?,? WHERE NOT EXISTS (SELECT 1 FROM table1 WHERE col1= ?);
但是当我使用普通插入查询时,我收到错误:
Caused by: org.postgresql.util.PSQLException: ERROR: duplicate key violates unique constraint "table1_pkey" (seg576 sdw24:40000 pid=398877)
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2062)
我已确保记录不重复但仍会出现此错误
我在哪里做错了? 我可以使用ORM将数据更新为postgres。如果是的话怎么样? 我可以使用jdbc模板将数据更新为postgres。如果是的话怎么样?
如何处理此异常?
答案 0 :(得分:0)
为了违反unique constraint,整个记录不一定必须是重复记录。唯一需要相同的列是构成约束的列。在这里,您提供的错误表明它是所涉及的table1_pkey
约束,因此您需要引用该约束的 DDL 来确定列。
从提供的代码中无法确定,但我怀疑发生的事情是列表中的两个项目({1}}中引用的任何属性都是相同的。
通常最好使用sequences来做这种事情(假设它是一个列),只要你让它使用默认值, Postgres 就会填充它自己(并使默认值正确递增序列 - serial
类型是语法糖,它会自动执行此操作)。
此外,当只涉及一个列时,它本来是主键,它可以声明为内联,所以在 DDL :table1_pkey
< / p>
如果涉及多个列,则应用相同的一般概念,但您不会以完全相同的方式定义主键(它稍后将定义为约束,因为它将包含列元组),您需要确保使用多个序列。
对OP评论的回应:
如果记录已经存在,尝试再次插入它们将在定义上违反唯一约束。您是在单个插入操作下混合插入和更新案例吗?那样不行。更新和插入需要分开。您可以通过在插入中添加id serial primary key
子选择来帮助防止插入中存在,这样当存在时,插入是无操作。更新仍然需要单独进行。
例外是upsert,它是9.5中Postgres的新功能,适合您在这里寻找的内容。
来自doc:
ON CONFLICT DO UPDATE保证原子INSERT或UPDATE结果; 如果没有独立错误,那么这两个结果之一就是 即使在高并发性下也能保证。这也称为UPSERT - “更新或插入”。
答案 1 :(得分:0)
我有一次类似的问题而且它不是由作家bean引起的。
在我的情况下,问题是因为我使用的是非线程安全的阅读器,所以我的源码阅读(随意)有些不止一次。
在您的示例源中,我只能看到编写器声明。
我建议您检查阅读器,如果您需要并行阅读器,请使用正确的阅读器或考虑使用顺序阅读器。