You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

H2数据库中正确填充ManyToMany关联表的方法求助

解决H2数据库ManyToMany关联表插入外键约束错误的问题

首先咱们来拆解下你遇到的问题根源:
你用了GenerationType.IDENTITY作为ID生成策略,这意味着H2会自动给sessions.session_id和speakers.speaker_id生成自增ID。但你的data.sql里插入主表数据时没指定ID值,插入中间表session_speakers却用了(1,40)这类固定ID——要么这些ID在主表里根本不存在,要么和数据库自动生成的ID不匹配,自然触发了外键约束错误。

下面给你两种实用的解决思路:

方法一:显式指定主表ID,保证与中间表ID完全匹配

这是最直接有效的方案,修改你的data.sql脚本,在插入sessions和speakers时明确写出ID字段的值,确保中间表引用的ID在对应主表中存在:

-- 插入sessions时指定session_id
INSERT INTO sessions (session_id, session_name,session_length,session_description) VALUES 
(1,'Keynote - The Golden Age of Software',45,''), 
(2,'A Better Way to Access Data with Spring Data',60,''), 
(3,'A Deep Dive Into Spring IoC',60,'');

-- 插入speakers时指定speaker_id
INSERT INTO speakers (speaker_id, first_name,last_name,title,company,speaker_bio) VALUES 
(40,'Sergio','Becker','Senior Developer','MicroOcean Software','Test'), 
(4,'James','Lowrey','Solutions Architect','Fabrikam Industries','Test');

-- 插入中间表,此时session_id和speaker_id都能在主表找到对应记录
INSERT INTO session_speakers (session_id,speaker_id) VALUES (1,40), (2,4), (3,5);

方法二:调整自增序列起始值(适合不想手动指定ID的场景)

如果你希望保持自动生成ID的逻辑,可以先修改H2的自增序列起始值,让自动生成的ID和你中间表用到的ID匹配:

-- 重置sessions表的session_id自增起始值
ALTER TABLE sessions ALTER COLUMN session_id RESTART WITH 1;
-- 重置speakers表的speaker_id自增起始值
ALTER TABLE speakers ALTER COLUMN speaker_id RESTART WITH 4;

-- 插入主表数据(无需指定ID,数据库会按设置的起始值自增)
INSERT INTO sessions (session_name,session_length,session_description) VALUES 
('Keynote - The Golden Age of Software',45,''), 
('A Better Way to Access Data with Spring Data',60,''), 
('A Deep Dive Into Spring IoC',60,'');

INSERT INTO speakers (first_name,last_name,title,company,speaker_bio) VALUES 
('James','Lowrey','Solutions Architect','Fabrikam Industries','Test'), 
('Sergio','Becker','Senior Developer','MicroOcean Software','Test');

-- 插入中间表,此时自动生成的ID会和你预期的一致
INSERT INTO session_speakers (session_id,speaker_id) VALUES (1,2), (2,1);

小贴士:这种方法需要你理清数据插入顺序和自增序列的对应关系,避免出现ID错位的情况。

额外注意点

  • 你现有data.sql的执行顺序是对的:先插主表,再插中间表,这个逻辑不用改。
  • 确认spring.jpa.hibernate.ddl-auto=create配置生效:它会在每次测试时重建表,避免旧数据干扰新的插入操作。

内容的提问来源于stack exchange,提问作者Rafał Popławski

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 17:52:48