Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java PostgreSQL JDBC getGeneratedKeys返回所有列_Java_Postgresql_Jdbc - Fatal编程技术网

Java PostgreSQL JDBC getGeneratedKeys返回所有列

Java PostgreSQL JDBC getGeneratedKeys返回所有列,java,postgresql,jdbc,Java,Postgresql,Jdbc,我最近在一个项目的后端从MySQL切换到PostgreSQL,发现我的一些数据库代理方法需要检查。要插入链接对象,我使用事务来确保所有内容都已存储。我使用jdbc方法来实现这一点,比如setAutoCommit(false)和commit()。我编写了一个实用方法,它将记录插入表中并返回生成的键。基本上我遵循了这里描述的技术2: 这在项目开始时就起作用了,但是在从MySQL迁移到PostgreSQL之后,getGeneratedKeys返回新插入记录的所有列(请参见下面的控制台输出) 代码:

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

这在项目开始时就起作用了,但是在从MySQL迁移到PostgreSQL之后,
getGeneratedKeys
返回新插入记录的所有列(请参见下面的控制台输出)

代码:

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

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
返回所有列,而不仅仅是生成的键?我在这里搜索并找到了其他有类似问题的人:


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

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

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

注意:如果未指定表示自动生成键的列,JDBC驱动程序实现将确定最能表示自动生成键的列

在字里行间,你可以说这允许说“我不知道,或者这是太多的工作了,所以所有的列最好代表自动生成的键”

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

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

其他解决方案是使用接受or的替代方法显式指定要返回的列名或列位置(尽管我不能100%确定PostgreSQL驱动程序如何处理)


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

更新-接受的答案(按标记)正确地解释了问题所在。我的解决方案也有效,但这只是因为我在重新创建表时首先添加了PK列。无论哪种方式,所有列都由
getGeneratedKeys()
返回

经过一些研究,我终于找到了问题的可能原因。正如我之前所说,在软件项目的开发过程中,我从MySQL改为PostgreSQL。对于这次迁移,我采用了一个SQL转储,并将其加载到PostgreSQL中。除了迁移的表之外,我还创建了一些新表(使用pgAdmin III中的GUI向导)。在仔细调查了两个表(一个导入,一个创建)之间的差异后,我确定了两件事:

  • MySQL转储中的
    CREATE TABLE
    语句将PKs转换为
    BIGINT NOT NULL
    ,而不是
    SERIAL
    。这导致自动生成的PKs不再正常工作,尽管我在问这个问题之前已经解决了这个问题

  • 我通过添加新序列并将其链接而“修复”的表工作得非常好,但SQL生成代码(由pgAdmin III自动生成,如原始问题所示)与PostgreSQL中生成的表不同

  • 请注意,我的固定表工作(ed)非常好:我可以插入记录、更新记录和执行连接。。。基本上做任何事。主键自动生成,序列更新。但是,JDBC驱动程序(精确地说是psotgresql-9.2-1003.jdbc4.jar)无法返回我生成的键(尽管这些表功能齐全)

    为了说明迁移表和创建表之间的区别,下面是我在迁移后添加的表的生成代码示例:

    CREATE TABLE configuration.configuration_xpathitem
    (
      xpathitemid serial NOT NULL,
      xpathid integer,
      fk_id_c integer,
      itemname text,
      index integer,
      CONSTRAINT pk_configuration_xpathitem PRIMARY KEY (xpathitemid),
      CONSTRAINT fk_configuration_xpathitem_configuration FOREIGN KEY (fk_id_c)
          REFERENCES configuration.configuration (id_c) MATCH SIMPLE
          ON UPDATE NO ACTION ON DELETE NO ACTION,
      CONSTRAINT fk_configuration_xpathitem_configuration_xpath FOREIGN KEY (xpathid)
          REFERENCES configuration.configuration_xpath (xpathid) MATCH SIMPLE
          ON UPDATE NO ACTION ON DELETE NO ACTION
    )
    
    您可以在这里清楚地看到我的PK有
    serial
    关键字,对于迁移(和固定)的表,它是
    integer not null default…

    因此,我认为PostgreSQL的JDBC驱动程序可能无法找到PK。我已经阅读了@Mark在回复中强调的规范,这让我认为这就是驱动程序返回所有列的原因。这让我相信驱动程序找不到PK,因为我认为它正在寻找
    serial
    关键字


    为了解决这个问题,我转储了数据,删除了有问题的表,然后再次添加它们,这次是从头开始,而不是使用MySQL转储中的SQL语句,然后重新加载了数据。这为我解决了问题。我希望这能帮助那些同样陷入困境的人。

    谢谢你的回复。虽然你说的是真的,但这不是问题的原因。我已经用不同的postgresql数据库创建了一个测试环境,在那里一切正常。我已经能够定位并同时解决问题
    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
    )
    
    CREATE SEQUENCE configuration.configuration_xpath_id_seq
      INCREMENT 1
      MINVALUE 1
      MAXVALUE 9223372036854775807
      START 242
      CACHE 1
      OWNED BY configuration.configuration_xpath.xpathid;
    
    CREATE TABLE configuration.configuration_xpathitem
    (
      xpathitemid serial NOT NULL,
      xpathid integer,
      fk_id_c integer,
      itemname text,
      index integer,
      CONSTRAINT pk_configuration_xpathitem PRIMARY KEY (xpathitemid),
      CONSTRAINT fk_configuration_xpathitem_configuration FOREIGN KEY (fk_id_c)
          REFERENCES configuration.configuration (id_c) MATCH SIMPLE
          ON UPDATE NO ACTION ON DELETE NO ACTION,
      CONSTRAINT fk_configuration_xpathitem_configuration_xpath FOREIGN KEY (xpathid)
          REFERENCES configuration.configuration_xpath (xpathid) MATCH SIMPLE
          ON UPDATE NO ACTION ON DELETE NO ACTION
    )