簡體   English   中英

如何使用JDBC和HSQLDB檢索以前自動生成的PK ID值

[英]How to retrieve previously auto-generated PK ID value using JDBC and HSQLDB

我正在使用JDBC和HSQLDB 2.2.9。 將新行插入數據庫並隨后保留其id (PK設置為自動增量)值的最有效和准確的方法是什么? 我需要這樣做的原因可能非常明顯,但我將舉例說明:

假設有一個Customer表,其PersonId字段的FK約束引用了Person表中的一行。 我想創建一個新的Customer ,但為了做到這一點,我需要先創建一個新的Person並使用新的Person.id值來設置Customer.PersonId

我已經看到了四種方法:

  1. Person行設置id字段插入null HSQLDB自動生成下一個id值。 然后在Person表上執行查詢以獲取剛剛創建的id值,並使用它來創建新的Customer行。

    這對於檢索單個整數值來說似乎很昂貴。

  2. 獲取Person表中的下一個id值,並在INSERT語句中使用它來手動設置Person.id值。 使用相同的id值來設置Customer.PersonId 不需要隨后從DB讀取。

    如果獲得了id值,則可能會出現不一致,但在執行INSERT INTO Person...語句之前,另一個連接在表中執行INSERT

  3. 執行INSERT語句,如上面的選項1所示,設置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值由連接產生的(如解釋在這里和在提到這個 SO問題)。

    這似乎也是一個合理的選擇,即使我必須執行額外的executeQuery 從積極的方面來說,我實際上能夠使用以下代碼:

     // 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... 

總而言之,前兩個選項我並不瘋狂。 第二個似乎沒問題,但我只能選擇4來工作。 哪個選項更受歡迎?為什么? 如果選項3是最好的,我做錯了什么? 還有,有沒有更好的方法,我沒有提到? 我知道像'更好'這樣的詞可以是主觀的,但我正在使用一個簡單的數據庫,並希望最直接的解決方案不會打開數據庫可能的不一致,並且不會增加事務失敗率(由於嘗試創建一個已經存在的id的記錄。

這似乎是一個基本問題(也是必不可少的),但我找不到最佳方法的指導。 謝謝。


編輯:我剛剛發現這個問題討論我的選項3.根據接受的答案,似乎我省略了啟用該功能所需的Statement.RETURN_GENERATED_KEYS參數。 我沒有在我的代碼片段中顯示prepareStatement方法,但我使用的是單參數版本。 我需要重試使用重載的雙參數版本。

還有一些其他SO問題出現在與我的問題密切相關的問題上。 所以,我想我的可能被視為重復(不知道我之前是否錯過了其他問題)。 但我仍然喜歡任何一個解決方案被認為比其他解決方案更好的指導。 現在,如果我讓選項3工作,我可能會繼續這樣做。

我沒有足夠的聲譽評論neizan的答案,但這是我如何解決同樣的問題:

  • 該列看起來像一個ID列,但它沒有被定義為IDENTITY;
  • 如上所述,您需要指定RETURN_GENERATED_KEYS。
  • 看起來如果按順序執行2 INSERT,第二個將不返回生成的鍵。 請改用“CALL IDENTITY()”。

使用HSQLDB 2.2.9的示例:

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

然后在Java中:

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);
    }
}

這里行動不多,所以我會繼續回答這個問題。 在玩了不同的選項之后,在看到這個問題后,我能夠讓我的選項3工作。 就像我在編輯問題中提到的那樣,我將使用選項3.選項4也工作正常,但由於鏈接問題的接受答案是由信譽良好的來源提供的,所以我堅持這一點。 我希望在開始這個問題之前我已經看過那個問題/答案,我已經節省了一些時間!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM