2

我正在使用 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>
4

2 回答 2

1

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

如果您想RETURNING id用作某种优化,那么您需要确定 JDBI 是否有 API 可以访问Connection.preparedStatement(String query, String[] columnNames)(据我所知它没有)。

唯一的其他选择是提交对 pgjdbc 的改进请求。

于 2016-01-02T08:31:46.057 回答
0

使用connection.prepareStatement(sql)代替connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)

于 2016-07-24T10:06:19.400 回答