5

最近、プロジェクトのバックエンドを MySQL から PostgreSQL に切り替えたところ、データベース プロキシ メソッドのいくつかを確認する必要があることがわかりました。リンクされたオブジェクトを挿入するには、トランザクションを使用してすべてが保存されていることを確認します。setAutoCommit(false)やなどの jdbc メソッドを使用してこれを行いますcommit()。テーブルにレコードを挿入し、生成されたキーを返すユーティリティ メソッドを作成しました。基本的に、ここで説明されているように、テクニック 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

しかし、彼らの質問には回答がなく、提案された回避策のみが提供されています。

4

2 に答える 2

11

ほとんどのドライバーは、自動生成される列を使用して、クエリの最後に -clause を追加することでサポートgetGeneratedKeys()します。PostgreSQL は、単純にすべての列を返すRETURNINGため、すべてのフィールドを返します。RETURNING *つまり、生成されたキーを返すために、返す列を決定するためにシステム テーブルにクエリを実行する必要がなく、ネットワーク ラウンドトリップ (およびクエリ時間) を節約できます。

これは、JDBC 仕様によって暗黙的に許可されています

: 自動生成されたキーを表す列が指定されていない場合、JDBC ドライバーの実装によって、自動生成されたキーを最もよく表す列が決定されます。

行間を読むと、これにより「わからない、または作業が多すぎるため、すべての列が自動生成されたキーを最も適切に表している」と言うことができます。

追加の理由は、どの列が自動生成され、どの列がそうでないかを判断するのが非常に難しいことかもしれません (これが PostgreSQL に当てはまるかどうかはわかりません)。たとえば、Jaybird (私が管理している Firebird の JDBC ドライバー) では、すべての列を返します。これは、Firebird ではどの列が自動生成されるかを判断できないためです (ただし、Firebird 3以前はありませんRETURNING *)。

ResultSetそのため、生成されたキーを位置ではなく列名で明示的にクエリすることを常にお勧めします。

String[]他の解決策は、またはを受け入れる代替メソッドを使用して、返される列名または列位置を明示的に指定していますint[](ただし、PostgreSQL ドライバーがそれをどのように処理するかは 100% わかりません)。

ところで: Oracle は (だった?) さらに悪い: デフォルトではROW_ID行の

于 2013-11-04T12:28:45.037 に答える