使用预准备语句

时间:2016-05-26 21:43:47

标签: java postgresql prepared-statement spring-batch

我正在尝试使用预准备语句将记录插入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。如果是的话怎么样?

如何处理此异常?

2 个答案:

答案 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引起的。

在我的情况下,问题是因为我使用的是非线程安全的阅读器,所以我的源码阅读(随意)有些不止一次。

在您的示例源中,我只能看到编写器声明。

我建议您检查阅读器,如果您需要并行阅读器,请使用正确的阅读器或考虑使用顺序阅读器。