java - PostgreSQL JDBC getGeneratedKeys 返回所有列

标签 java postgresql jdbc

我最近从 MySQL 切换到 PostgreSQL 用于项目的后端,并发现我的一些数据库代理方法需要审查。为了插入链接对象,我使用事务来确保所有内容都已存储。我使用诸如 setAutoCommit(false)commit() 之类的 jdbc 方法来执行此操作。我编写了一个实用程序方法,可将记录插入表中并返回生成的键。基本上我遵循了这里描述的技术 2:

http://www.selikoff.net/2008/09/03/database-key-generation-in-java-applications/

这从项目开始就有效,但在从 MySQL 迁移到 PostgreSQL 之后 getGeneratedKeys 返回新插入记录的所有列(见下面的控制台输出) .

代码:

final ResultSet keys = ps.getGeneratedKeys();
final ResultSetMetaData metaData = keys.getMetaData();
for (int j = 0; j < metaData.getColumnCount(); j++) {
    System.out.println("Col name: "+metaData.getColumnName(j+1));
}

输出:

Col name: pathstart
Col name: fk_id_c
Col name: xpathid
Col name: firstnodeisroot

表的数据库签名(从 pgAdmin III 自动生成的 SQL):

CREATE TABLE configuration.configuration_xpath
(
  pathstart integer NOT NULL,
  fk_id_c integer NOT NULL,
  xpathid integer NOT NULL DEFAULT nextval('configuration.configuration_xpath_id_seq'::regclass),
  firstnodeisroot boolean NOT NULL DEFAULT false,
  CONSTRAINT configuration_xpath_pkey PRIMARY KEY (xpathid),
  CONSTRAINT configuration_fk FOREIGN KEY (fk_id_c)
      REFERENCES configuration.configuration (id_c) MATCH SIMPLE
      ON UPDATE CASCADE ON DELETE CASCADE
)

PK 背后序列的数据库签名:

CREATE SEQUENCE configuration.configuration_xpath_id_seq
  INCREMENT 1
  MINVALUE 1
  MAXVALUE 9223372036854775807
  START 242
  CACHE 1
  OWNED BY configuration.configuration_xpath.xpathid;

所以问题是,为什么 getGeneratedKeys 返回所有列而不是仅返回生成的键?我在这里搜索并发现其他人也有类似的问题:

http://www.postgresql.org/message-id/004801cb7518$cbc632e0$635298a0$@pravdin@disi.unitn.it

但是他们的问题没有得到回答,只提供了一个建议的解决方法。

最佳答案

大多数驱动程序通过在查询末尾添加一个 RETURNING 子句和自动生成的列来支持 getGeneratedKeys()。 PostgreSQL 返回所有字段,因为它有 RETURNING * ,它只返回所有列。这意味着要返回生成的键,它不必查询系统表来确定要返回的列,这样可以节省网络往返(和查询时间)。

这是 JDBC 规范隐式允许的,因为它 says :

Note:If the columns which represent the auto-generated keys were not specified, the JDBC driver implementation will determine the columns which best represent the auto-generated keys.

从字里行间你可以说这允许说'我不知道,或者工作量太大,所以所有列最好代表自动生成的键'。。 p>

另一个原因可能是很难确定哪些列是自动生成的,哪些不是(我不确定 PostgreSQL 是否如此)。例如,在 Jaybird(我维护的 Firebird 的 JDBC 驱动程序)中,我们还返回所有列,因为在 Firebird 中,不可能确定哪些列是自动生成的(但我们确实需要查询系统表以获取列名,因为 Firebird 3和更早的版本没有 RETURNING *)。

因此,始终建议按列名而不是按位置显式查询生成的键 ResultSet

其他解决方案使用接受 String[] 的替代方法显式指定您希望返回的列名或列位置或 int[] (虽然我不是 100% 确定 PostgreSQL 驱动程序如何处理它)。

顺便说一句:Oracle 现在(曾经?)更糟:默认情况下它返回行的 ROW_ID,您需要使用单独的查询从该行获取(生成的)值。

关于java - PostgreSQL JDBC getGeneratedKeys 返回所有列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19766816/

相关文章:

java - 无法理解 Shiro 在自定义登录页面请求上的行为

mysql - 哪个数据库支持插入越南语字符?

postgresql - 在 SQL 事务中获取实体的 id 字段

java - 将 DATETIME 从 SQLite 解析为 java.SQL.Timestamp 时出错

java - Oracle11g安装监听器错误

java - SWT:防止树通过双击展开?

java - 根据参数/用户选择更新 sqlite 表属性

java - 解析整数时出现 NumberFormatException

sql - 如何连接两个表 A 和 B 以获得 A 中的非连接列且数据不在 B 中?

postgresql - 在 sql 中使用 Windows 函数运行总计对于相同的数据具有相同的结果