Hibernate JPA一对多保存操作出现主键重复约束违反问题求助
解决JPA多对多关联保存时的主键重复问题
你的核心问题是错误使用了@OneToMany注解,Item和Event实际是多对多关系(一个Item对应多个Event,一个Event对应多个Item),而非一对多。一对多会强制每个Event只能属于一个Item,加上cascade=CascadeType.ALL后,保存第二个Item时会重复插入已存在的Event,导致主键约束冲突。以下是具体解决方案:
1. 修正实体类的关联配置
Item实体类修改
将@OneToMany替换为@ManyToMany,通过@JoinTable指定中间表结构,同时调整级联类型避免不必要的操作:
@Entity @Table(name = "item", schema = "demo_transaction") public class Item { @Id Integer item_id; String itemName; Integer price; // 多对多关联,指定中间表信息 @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}) @JoinTable( name = "item_event", // 自定义中间表名称 schema = "demo_transaction", joinColumns = @JoinColumn(name = "item_id"), // 关联当前实体的字段 inverseJoinColumns = @JoinColumn(name = "event_id") // 关联Event实体的字段 ) List<Event> events; // 构造方法、Getter/Setter 请自行补充 }
Event实体类修改
添加双向多对多关联,指定由Item端维护关联关系:
@Entity @Table(name = "event", schema = "demo_transaction") public class Event { @Id Integer event_id; String eventName; // 双向多对多,mappedBy指向Item端的关联字段名 @ManyToMany(mappedBy = "events") List<Item> items; // 构造方法、Getter/Setter 请自行补充 }
注意:移除实体类上的
@Transactional注解,事务管理应该放在Service层方法上,而非实体类。
2. 调整保存逻辑
由于现在是多对多关系,需要确保Event实例在数据库中存在后,再关联到Item保存,或者利用级联类型自动处理:
// 先保存Event实例(确保数据库中存在这两个事件) Event e1 = new Event(10, "FirstEvent"); Event e2 = new Event(20, "SecondEvent"); eventRepo.save(e1); eventRepo.save(e2); // 为Item1关联事件 List<Event> lse1 = new ArrayList<>(); lse1.add(e1); lse1.add(e2); Item item1 = new Item(1, "FirstItem", 600, lse1); // 为Item2关联事件 List<Event> lse2 = new ArrayList<>(); lse2.add(e1); lse2.add(e2); Item item2 = new Item(2, "SecondItem", 200, lse2); // 保存Item,此时只会插入中间表的关联记录,不会重复插入Event repo.save(item1); repo.save(item2);
如果不想手动提前保存Event,也可以依赖CascadeType.PERSIST和CascadeType.MERGE的组合:当Event不存在时会自动插入,已存在时会合并关联关系,不会重复插入导致主键冲突。
完成以上修改后,中间表item_event会生成你期望的结构:
item_id event_id 1 10 1 20 2 10 2 20
内容的提问来源于stack exchange,提问作者SUVAM ROY
相关产品推荐
相关产品推荐

