MySQL - 外键和自动生成的ID

时间:2012-09-11 07:56:44

标签: java mysql jdbc auto-increment

在我的应用程序中,我有一个组件从另一个组件接收对象并将它们插入MySQL DB。目前我正在缓冲对象,偶尔(几秒钟)使用批处理(使用JDBC,而不是休眠)将对象插入到数据库中。

我想将这个对象分解为2个对象,然后是两个缓冲区,最后将它们插入到2个不同的表中。

我的第一个想法是使用MySQL自动生成的ID将表中的两个子对象绑定在一起(作为外键)。

我的问题是 - 当我插入'child'对象时,如何知道'father'对象的自动生成的ID?

我的想法是:

  1. 在拆分对象之前生成我自己的ID,并自己将ID发送到DB,而不使用MySQL自动生成的ID。
  2. 使用将插入第一个对象的存储过程,使用MySQL的LAST_INSERT_ID();
  3. 你怎么看?

5 个答案:

答案 0 :(得分:1)

一种解决方案是将两条记录插入到与此问题相同的事务中。 JDBC: foreign key on PK created in same transaction

那是:

  1. 初始化交易。
  2. 做父亲的第一次插入。
  3. 检索生成的父ID。
  4. 使用父ID进行孩子的第二次插入。
  5. 提交交易。

答案 1 :(得分:0)

也许这会有所帮助(您也可以在纯SQL中使用LAST_INSERT_ID(),而不仅仅是在程序内部),另请参阅http://dev.mysql.com/doc/refman/5.0/en/getting-unique-id.html

INSERT INTO foo (auto,text) VALUES(NULL,'text');         # generate ID by inserting NULL
INSERT INTO foo2 (id,text)  VALUES(LAST_INSERT_ID(),'text');  # use ID in second table

鉴于OP在不同的线程上运行INSERT,需要预先分配ID - 您可以使用序列来安全地选择唯一ID(另请参阅MySQL information functions):

  
      
  • 创建一个表来保存序列计数器并对其进行初始化:

         

    的MySQL> CREATE TABLE序列(id INT NOT NULL);

         

    的MySQL> INSERT INTO序列值(0);

  •   
  • 使用该表生成如下序列号:

         

    的MySQL> UPDATE序列SET id = LAST_INSERT_ID(id + 1);

         

    的MySQL> SELECT LAST_INSERT_ID();

  •   

答案 2 :(得分:0)

两种方法都有效。
Java方法与数据库无关,可能更容易切换数据库或支持多个数据库供应商。

答案 3 :(得分:0)

您的基本问题是,在存储其他对象之前,您需要数据库中有关一个对象的信息。

假设您将复合对象拆分为两个较小的对象,即Place和Map。

如果您必须有两个缓冲区来存储Place和Map,那么我会看到三种方法:

  1. 只将Place放入商店缓冲区。存储Place并且已从数据库中读取PK时,只需将Map放在另一个存储缓冲区中。

  2. 将Place和Map放在他们自己的商店缓冲区中。当即将存储地图时,检查它是否与相关联的地方,以查看是否已生成PK。如果有,则存储地图。如果没有,则跳过该地图并检查下一个地图。

  3. 放置在商店缓冲区中。存储后,读取PK,并立即存储Map。这显然不使用两个存储缓冲区。

  4. 查看应用程序中其他对象的存储方式。当然,在将它们存储在数据库中之前,它们不会生成自己的ID。当然,在获得存储它们所需的所有信息之前,不要尝试将它们放在存储缓冲区中。因此,我推荐的行动方案是选项1或3。

答案 4 :(得分:0)

使用JDBC检索生成密钥的标准接口是在语句中使用getGeneratedKeys()方法。请参阅MySQL站点的Example 21.8. Connector/J: Retrieving AUTO_INCREMENT column values using