2013-07-25 12 views
5

私はJDBCとHSQLDB 2.2.9を使っています。 DBに新しい行を挿入し、その後、id(PKは自動インクリメントに設定)の値を保持する最も効率的で正確な方法は何ですか?私はこれを行う必要がある理由は、おそらくかなり明白ですが、私は議論のための例を示します:JDBCとHSQLDBを使用して以前に自動生成されたPK ID値を取得する方法

FK制約がPersonテーブルから行を参照してPersonIdフィールドを持つCustomerテーブルがあると言います。新しいCustomerを作成しますが、これを行うには、最初に新しいPersonを作成し、新しいPerson.id値を使用してCustomer.PersonIdを設定する必要があります。

私はこれをアプローチする4つの方法を見てきました:

  1. nullidフィールドを設定Person行を挿入します。 HSQLDBは​​自動的に次のid値を生成します。次にPersonテーブルのクエリを実行してidの値を作成し、それを使用して新しいCustomer行を作成します。

    これは、単一の整数値を取得するだけでは高額に見えます。

  2. Person表の次のid値を取得し、手動でPerson.id値を設定するINSERT文の中でそれを使用します。同じid値を使用してCustomer.PersonIdを設定します。その後のDBからの読み取りは必要ありません。

    idの値が取得されても、別の接続がINSERT INTO Person...文が実行される前にテーブルにINSERTを実行すると、不一致が発生することがあります。

  3. 上記のオプション1のようにINSERTステートメントを実行し、自動生成を許可するようにid=nullを設定します。次に、getGeneratedKeysメソッドを使用して、最後のステートメントで生成されたキーを取得します。

    これは良い選択肢のように思えましたが、動作させることができませんでした。ここに私のコードの抜粋です:

    // PreparedStatement prepared previously... 
    preparedStatement.executeUpdate(); 
    ResultSet genKeys = preparedStatement.getGeneratedKeys(); 
    int id; 
    if (genKeys.next()) { 
        id = genKeys.getInt(1); 
    } 
    // Finish up method... 
    

    このコードはgenKeysのための空のResultSetを返していました。 getGeneratedKeysメソッドを間違って使用していますか?私はこれを働かせることができれば、これは行く方法かもしれない。

  4. INSERTステートメントを実行して、自動生成idを実行します。その後すぐにCALL IDENTITY()を実行して、接続によって生成された最後のidの値を取得します(hereと説明されており、thisの質問に記載されています)。

    私は追加のexecuteQueryを実行する必要がありますが、これは合理的な選択肢のようです。要約すると、最初の2つのオプションは、私は夢中ではないよ、だから、

    // INSERT statement executed here... 
    statement = connection.createStatement(); 
    ResultSet rs = statement.executeQuery("CALL IDENTITY();"); 
    int id; 
    if (rs.next()) id = rs.getInt(1); 
    // Finish up method... 
    

:正側では、私は実際にそれが次のコードで動作するように取得することができました。後の2つは大丈夫だと思われますが、私は選択肢4を働かせるだけです。どちらのオプションが優先され、なぜですか?オプション3が最高の場合、何が間違っているのですか?また、私が言及していないより良い方法がありますか?私は 'better'のような言葉が主観的であることは知っていますが、私は単純なDBを使って作業しており、可能性のある不一致にDBを開放しない最も直接的な解決策を求めています。すでに存在するidのレコードを作成します)。

これは基本的な質問(および必須)のようですが、私はそれを行う最良の方法について多くの指針を見つけることができませんでした。ありがとう。


編集:私はちょうど受け入れ答えによると、私のオプション3を説明し this質問を見つけ 、私がその機能を有効にするために必要な Statement.RETURN_GENERATED_KEYSパラメータを除外して表示されます。自分のコードスニペットに prepareStatementメソッドを表示しませんでしたが、私は単一のパラメータバージョンを使用していました。オーバーロードされた2パラメータバージョンを使用して再試行する必要があります。

私の質問に密接に関連しているこの質問には、他にもいくつかの質問があります。だから、私は私が重複していると思うかもしれないと思う。しかし、私はまだ、あるソリューションが他のソリューションよりも優れているかどうかについてのガイダンスを欲しがっています。今のところ、オプション3を稼働させると、おそらくこれで動くでしょう。

+0

正直に言うと、私はあなたのソリューションNo1のに固執won't理由を知るドント。新しく挿入された行のIDでSELECTを実行すると、通常はクエリのオーバーヘッドが発生しますが、他のオプションもすべて同じです。 –

+0

私は 'id'で' SELECT'するのではなく、別の一意のキーを構成する他のフィールドの束にします。 'id'の値は私が探している値になります。しかし、 "クエリの通常のオーバーヘッド"に関するあなたのコメントは、クエリの詳細にかかわらず、まだ立っています。しかし、オプション3に伴うオーバーヘッドについてはわかりませんでした。前のステートメント実行から情報が残っていると思いました。オプション4では、 'CALL IDENTITY()'のクエリを "通常の" SELECT文よりも安価に実行できたかどうかはわかりませんでした。 – neizan

+0

もしそうなら、私は知らない。個人的には、挿入後に1つのクエリーについて心配するつもりはありませんが、当然あなたの仕事の詳細はわかりません。 –

答えて

1

ここではあまり行動しないので、私はこの質問に閉鎖をもたらすために進んで答えます。さまざまなオプションで遊んだ後、thisの質問をした後、私は自分の選択肢3を働かせることができました。私の質問に編集で述べたように、私はオプション3を使用するつもりです。オプション4もうまくいきましたが、リンクされた質問に対する受け入れられた答えが評判の良い情報源によって与えられているので、私はそれに固執しています。私はこの質問/回答を見て、この1つを開始する前に、私は時間を節約していたはずです。

+3

オプション3は、INSERTステートメントが完了したときに生成されたキーが返され、他のオプションが必要とする余分な操作を最小限に抑えるため、最適です。 – fredt

+0

それは私が考えたことであり、私がそのオプションを持って行った主な理由です。フィードバックをお寄せいただきありがとうございます。 – neizan

+0

ORMを使用する場合は、すべての作業を行います。 [Sormula Identity Column](http://www.sormula.org/identity/)の例を参照してください。 –

7

私はneizanの答えにコメントするのに十分な評判を持っていますが、ここで私は同じ問題を解決する方法ですしていない:

  • 列がID列のように見えたが、それはIDENTITYとして定義されていません。
  • 上記のように、RETURN_GENERATED_KEYSを指定する必要があります。
  • 2 INSERTを順番に実行すると、2番目のINSERTが生成されたキーを返さないようです。代わりに "CALL IDENTITY()"を使用してください。 Javaで次に

    CREATE TABLE MY_TABLE (
    ID INTEGER IDENTITY, 
    NAME VARCHAR(30) 
    ) 
    

HSQLDB 2.2.9を使用して実施例

PreparedStatement result = cnx.prepareStatement(
    "INSERT INTO MY_TABLE(ID, NAME) VALUES(NULL, 'TOM');", 
    RETURN_GENERATED_KEYS); 
int updated = result.executeUpdate(); 
if (updated == 1) { 
    ResultSet generatedKeys = result.getGeneratedKeys(); 
    if (generatedKeys.next()) { 
     int key = generatedKeys.getInt(1); 
    } 
} 
関連する問題