如何创建支持多组多对多的公共关联表?现有配置为何不生效
现有配置不生效的原因
- 首先JPA的
@ManyToMany注解绑定的关联表默认仅用于维护两组实体的二元映射关系,每个@JoinTable配置会被识别为独立的映射规则。你给两个完全独立的多对多关联指定了同一个CARS作为关联表名时,JPA实现(比如Hibernate)处理表结构生成时会出现冲突:第一个关联会生成仅包含RANGE_ID、MODEL_ID的表结构,第二个关联的配置要么直接覆盖前一个规则生成仅包含RANGE_ID、TYPE_ID的表,要么抛出表结构已存在/不匹配的异常,不会自动合并两个配置的字段生成三列结构的表。 - 就算你手动创建三列的
CARS表,原有配置的逻辑也不符合你的预期:两个独立的多对多关联是完全解耦的,models关联插入数据时只会填充RANGE_ID和MODEL_ID,TYPE_ID会留空;types关联插入数据时只会填充RANGE_ID和TYPE_ID,MODEL_ID会留空,你永远得不到三列同时有值、能对应上range-model-type三者绑定关系的行。
正确配置方案
你期望的CARS表本质上是维护Range、Models、Types三者的三元关联,已经不属于单纯的二元多对多关联表,需要把它定义为独立实体来处理:
- 首先创建
Cars实体类对应关联表
@Entity @Table(name = "CARS") public class Cars { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @ManyToOne(optional = false) @JoinColumn(name = "RANGE_ID", referencedColumnName = "ID") private Range range; @ManyToOne(optional = false) @JoinColumn(name = "MODEL_ID", referencedColumnName = "ID") private Models model; @ManyToOne(optional = false) @JoinColumn(name = "TYPE_ID", referencedColumnName = "ID") private Types type; // 省略构造方法、getter、setter }
- 修改原
Range类中的关联配置,替换原有两个多对多关联
// Range类中 @OneToMany(mappedBy = "range", cascade = CascadeType.ALL, orphanRemoval = true) private List<Cars> cars; // 如果需要便捷获取当前Range下的所有Models和Types,可以增加派生方法 public List<Models> getAllModels() { return cars.stream() .map(Cars::getModel) .distinct() .toList(); } public List<Types> getAllTypes() { return cars.stream() .map(Cars::getType) .distinct() .toList(); }
后续你需要添加关联时,只需构造Cars实体实例,同时赋值range、model、type三个属性后持久化即可,生成的表结构完全符合你的预期。
内容的提问来源于stack exchange,提问作者Nikolay Grigoryev
相关产品推荐
相关产品推荐

