簡體   English   中英

*在*將數據庫插入MySQL JDBC之前*獲取AUTO_INCREMENT

[英]Get AUTO_INCREMENT *before* database insertion in MySQL JDBC

我正在使用JDBC開發MySQL數據庫項目。 它使用與外鍵鏈接的父/子表。

TL; DR:我希望能夠 INSERT語句之前獲取表的AUTO_INCREMENT ID。 我已經知道JDBC中的getGeneratedKeys()方法可以在插入后執行此操作,但是我的應用程序在插入之前需要ID。 對於這個特定的應用程序,也許有更好的解決方案? 詳情如下:


在此應用程序的一部分中,用戶可以通過表單或控制台輸入來創建新項目以輸入詳細信息-其中一些詳細信息以新項目中“子項目”的形式出現。

這些輸入存儲在Java對象中,因此表的每一行對應於這些對象之一-以下是一些示例:

MainItem
 - id (int)
 - a bunch of other details...

MainItemTitle 
 - mainItemId (int)
 - languageId (int)
 - title (String)

ItemReference
 - itemId (int) <-- this references MainItem id
 - referenceId (int) <-- this references another MainItem id that is linked to the first

因此,基本上每個Java對象都代表MySQL數據庫相關表中的一行。

當我將輸入中的值存儲到對象中時,將使用一個偽ID,如下所示:

private static final int DUMMY_ID = 0;

...

MainItem item = new MainItem(DUMMY_ID, ...);

// I read each of the titles and initialise them using the same dummy id - e.g.
MainItemTitle title = new MainItemTitle(DUMMY_ID, 2, "Here is a a title");

// I am having trouble with initialising ItemReference so I will explain this later

讀取用戶輸入后,它們將存儲在“ holder”類中:

class MainItemValuesHolder {

    MainItem item;
    ArrayList<MainItemTitle> titles;
    ArrayList<ItemReference> references;
    // These get initialised and have getters and setters, omitted here for brevity's sake
}

...

MainItemValuesHolder values = new MainItemValuesHolder();
values.setMainItem(mainItem);
values.addTitle(englishTitle);
values.addTitle(germanTitle);
// etc...

在應用程序的最后一層(在另一個類中,將值所有者作為參數傳遞),將讀取“ holder”類中的數據並將其插入數據庫中:

// First insert the main item, belonging to the parent table

MainItem mainItem = values.getMainItem();
String insertStatement = mainItem.asInsertStatement(true); // true, ignore IDs
// this is an oversimplification of what actually happens, but basically constructs the SQL statement while *ignoring the ID*, because...

int actualId = DbConnection.insert(insertStatement);
// updates the database and returns the AUTO_INCREMENT id using the JDBC getGeneratedKeys() method

// Then do inserts on sub-items belonging to child tables
ArrayList<MainItemTitle> titles = values.getTitles();
for (MainItemTitle dummyTitle : titles) {
    MainItemTitle actualTitle = dummyTitle.replaceForeignKey(actualId);
    String insertStatement = actualTitle.asInsertStatement(false); // false, use the IDs in the object
    DbConnection.insert(insertStatement);
}

現在,問題是將此過程用於ItemReference 因為它鏈接了兩個MainItem ,所以使用(或多個)虛擬ID預先構造對象會破壞這些關系。

最明顯的解決方案似乎是能夠預先獲取AUTO_INCREMENT ID,這樣我就不需要使用虛擬ID。

我想另一種解決方案是在輸入數據后立即插入數據,但是我寧願將應用程序的不同功能保留在單獨的類中,因此一個類負責一個操作。 此外,通過在輸入數據后立即插入,如果用戶選擇在輸入“主要項目”,標題,參考等所有數據之前選擇取消,則現在需要刪除無效數據。


總之, 插入之前如何獲得AUTO_INCREMENT 對於這個特定的應用程序有更好的解決方案嗎?

您不能在插入之前獲取該值。 您不知道桌上可能要采取的其他措施。 AUTO_INCREMENT可能不會增加1,您可能已經設置了該值,但是可以更改。

可以使用臨時表在您的控制下通過鍵存儲數據。 我建議使用Uuid而不是ID,這樣您就可以認為它永遠是唯一的。 然后您的其他類可以將數據復制到活動表中,您仍然可以使用Uuid鏈接數據以在臨時表中找到相關數據,但是按照對數據庫有意義的順序將其寫入(因此,“根” '先記錄下來以獲得密鑰,然后在需要時使用它。

暫無
暫無

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

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