我正在使用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
?对于这个特定的应用程序有更好的解决方案吗?
答案 0 :(得分:2)
在插入之前无法获取该值。您不知道桌上可能要采取的其他措施。 AUTO_INCREMENT可能不会增加1,您可能已经设置了该值,但是可以更改。
您可以使用临时表在您的控制下存储带有键的数据。我建议使用Uuid而不是ID,这样您就可以认为它永远是唯一的。然后您的其他类可以将数据复制到活动表中,您仍然可以使用Uuid链接数据以在临时表中找到相关数据,但是按照对数据库有意义的顺序将其写入(因此,“根” '先记录下来以获得密钥,然后在需要时使用它。