*在*将数据库插入MySQL JDBC之前*获取AUTO_INCREMENT

时间:2019-08-07 21:24:22

标签: java mysql jdbc sql-insert auto-increment

我正在使用JDBC开发MySQL数据库项目。它使用与外键链接的父/子表。

TL; DR:我希望能够在AUTO_INCREMENT语句之前获取表的INSERT 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 ?对于这个特定的应用程序有更好的解决方案吗?

1 个答案:

答案 0 :(得分:2)

在插入之前无法获取该值。您不知道桌上可能要采取的其他措施。 AUTO_INCREMENT可能不会增加1,您可能已经设置了该值,但是可以更改。

可以使用临时表在您的控制下存储带有键的数据。我建议使用Uuid而不是ID,这样您就可以认为它永远是唯一的。然后您的其他类可以将数据复制到活动表中,您仍然可以使用Uuid链接数据以在临时表中找到相关数据,但是按照对数据库有意义的顺序将其写入(因此,“根” '先记录下来以获得密钥,然后在需要时使用它。

相关问题