Hibernate多对多关联复合主键含公共字段映射异常排查
解决多对多关联中复合主键公共字段的映射异常
首先明确:多对多关联中完全可以包含公共字段,你遇到的Repeated column异常是因为关联映射的配置重复了,不是公共字段本身的问题。
问题根源
你在Shop和Categorie两个实体中都配置了@JoinTable,并且在两边的joinColumns和inverseJoinColumns里都包含了idAppli列。Hibernate处理时会认为同一个列被重复映射到同一个集合中,因此抛出异常。
解决方案:指定关联维护端,避免重复配置
多对多关联只需要在**一端(维护端)**配置@JoinTable,另一端(被维护端)通过mappedBy指向维护端的关联属性即可,这样就能复用同一份映射配置,避免重复列的问题。
1. 修改Shop类(维护端)的关联配置
保持@JoinTable的正确配置,对应复合主键的所有字段:
@Entity @Table(name = "tbShop") public class Shop implements Serializable { private static final long serialVersionUID = 1L; @EmbeddedId protected ShopPK shopPK; @Column(name = "commNom") private String name; @ManyToMany(fetch = FetchType.EAGER, cascade = {CascadeType.SAVE_UPDATE, CascadeType.ALL}) @JoinTable(name = "tbCategorieShop", // 关联当前Shop实体的复合主键字段 joinColumns = { @JoinColumn(name = "idAppli", referencedColumnName = "idAppli"), @JoinColumn(name = "idShop", referencedColumnName = "idShop") }, // 关联关联实体Categorie的复合主键字段 inverseJoinColumns = { @JoinColumn(name = "idCategorie", referencedColumnName = "idCategorie"), @JoinColumn(name = "idAppli", referencedColumnName = "idAppli") } ) private List<Categorie> tbCategorie ; // 省略getter、setter及序列化相关方法 }
2. 修改Categorie类(被维护端)的关联配置
移除@JoinTable,改用mappedBy指向Shop类中的tbCategorie属性:
@Entity @Table(name = "tbCategorie") public class Categorie implements Serializable { private static final long serialVersionUID = 1L; @EmbeddedId protected CategoriePK categoriePK; @Column(name = "categName") private String categName; // 通过mappedBy复用Shop端的关联配置 @ManyToMany(mappedBy = "tbCategorie") private Collection<Shop> shopCollection; // 省略getter、setter及序列化相关方法 }
关键说明
- 关联表
tbCategorieShop中的idAppli是两个实体复合主键的公共字段,作为外键同时关联Shop和Categorie的idAppli,这在数据库设计中是合理的。 - 只在维护端配置
@JoinTable,被维护端不重复配置,就能让Hibernate正确识别映射关系,避免重复列的错误。
内容的提问来源于stack exchange,提问作者cjg
相关产品推荐
相关产品推荐

