1

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

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

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

我的问题是 - 当我插入“子”对象时,如何知道“父”对象的自动生成 ID?

我的想法是:

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

你怎么看?

4

5 回答 5

1

一种解决方案是在此问题中所做的同一事务中插入两条记录。 JDBC:在同一事务中创建的 PK 上的外键

那是:

  1. 初始化事务。
  2. 做父亲的第一个插入。
  3. 检索生成的父亲 ID。
  4. 使用父亲 ID 执行子项的第二次插入。
  5. 提交事务。
于 2012-09-11T08:16:50.117 回答
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 信息函数):

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

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

    mysql> 插入序列值(0);

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

    mysql> 更新序列 SET id=LAST_INSERT_ID(id+1);

    mysql> SELECT LAST_INSERT_ID();

于 2012-09-11T08:14:19.430 回答
0

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

于 2012-09-11T08:21:24.077 回答
0

您的基本问题是,您需要从数据库中获取一个对象的信息,然后才能存储另一个对象。

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

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

  1. 仅将 Place 放在存储缓冲区中。当 Place 被存储,并且 PK 已经从数据库中读取时,只有将 Map 放在另一个存储缓冲区中。

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

  3. 将 Place 放入存储缓冲区。当它被存储时,读取 PK,并立即存储 Map。这显然不使用两个存储缓冲区。

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

于 2012-09-11T09:07:06.883 回答
0

使用 JDBC 检索生成的密钥的标准接口是使用getGeneratedKeys()语句上的方法。见例 21.8。连接器/J:使用从 MySQL 站点检索 AUTO_INCREMENT 列值

于 2012-09-11T17:13:07.990 回答