代码之家  ›  专栏  ›  技术社区  ›  THX1138

Pg jdbc使用现有的RETURNING子句在准备好的批次上附加RETURNING*

  •  2
  • THX1138  · 技术社区  · 10 年前

    我正在使用pg-jdbc/JDBI在Postgres表中执行准备好的批插入,以便使用显式RETURNING子句获得生成的id值列表:

    PreparedBatch b = getHandle().prepareBatch("INSERT INTO death_star(id,exhaust_port) VALUES ( :id, :exhaust_port) RETURNING id;");
    
    for (RebelPilot p : rebelPilots) {
        b.add().bind("id",p.getId()).bind("exhaust_port",p.getProtonTorpedo());
    }
    
    ResultSetMapper<Long> mapper = new IdMapper()
    GeneratedKeys<Long> gk = b.executeAndGenerateKeys(mapper);
    return gk.list()
    

    当语句准备好后,pg-jdbc会无意识地附加一个额外的 RETURNING * 在现有的 RETURNING 条款导致以下格式错误的憎恶:

    INSERT INTO death_star(id,exhaust_port) VALUES ( ?, ?) RETURNING id RETURNING *;
    

    如果我删除了显式的RETURNING子句,该语句可以正常工作;但是,它会导致返回目标表中的所有字段,这在插入大量数据的许多情况下是非常不可取的。

    有什么方法可以阻止pg-jdbc参与这种行为吗?

    测试依赖项:

    <dependency>
      <groupId>org.postgresql</groupId>
      <artifactId>postgresql</artifactId>
      <version>9.4.1207.jre7</version>
    </dependency>
    <dependency>
      <groupId>org.jdbi</groupId>
      <artifactId>jdbi</artifactId>
      <version>2.71</version>
    </dependency>
    
    2 回复  |  直到 5 年前
        1
  •  1
  •   Mark Rotteveel    10 年前

    您正在使用 executeAndGenerateKeys 可能会使用 Connection.prepareStatement(query, Statement.RETURN_GENERATED_KEYS) 。PostgreSQL JDBC生成的密钥实现将附加 RETURNING * 在这种情况下,它不会检查它是否已经存在于查询文本中)。您需要删除 RETURNING id 从您自己的查询中进行查询以使其正常工作。

    如果您想使用 返回id 作为某种优化,您需要了解JDBI是否有可访问的API Connection.preparedStatement(String query, String[] columnNames) (据我所知,它没有)。

    唯一的另一个选择是为pgjdbc提交改进请求。

        2
  •  0
  •   Thirumal    9 年前

    使用 connection.prepareStatement(sql) 而不是 connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)

    推荐文章