Hibernate复合主键下User与Bottom自定义一对多关联配置问询
解决方案
嘿,这个问题核心就是要自定义关联字段的映射逻辑,不让Hibernate默认生成多余列,具体改法如下:
1. 关键修改:Bottom实体类的@ManyToOne注解
你需要用@JoinColumns明确指定关联的字段对应关系,把User的schoolId和Bottom的schoolId绑定,同时把User的uId和Bottom的cId绑定。另外要给这两个@JoinColumn加上insertable = false, updatable = false——因为这两个字段已经是Bottom复合主键的一部分,不能通过关联关系去修改它们的增删操作,避免冲突:
@IdClass(BottomId.class) @Entity class Bottom { @Id private String bId; @Id private String cId; @Id private String schoolId; @ManyToOne @JoinColumns({ // 关联User的schoolId到当前实体的schoolId @JoinColumn(name = "schoolId", referencedColumnName = "schoolId", insertable = false, updatable = false), // 关联User的uId到当前实体的cId @JoinColumn(name = "cId", referencedColumnName = "uId", insertable = false, updatable = false) }) private User user; }
2. 别忘了复合主键类的必要实现
这里提醒一下,你的UserId和BottomId这两个复合主键类,必须正确实现equals()和hashCode()方法,Hibernate对复合主键有这个硬性要求,不然会出现主键匹配异常或者缓存问题。比如BottomId可以这样写:
import java.util.Objects; class BottomId { private String bId; private String cId; private String schoolId; @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; BottomId bottomId = (BottomId) o; return Objects.equals(bId, bottomId.bId) && Objects.equals(cId, bottomId.cId) && Objects.equals(schoolId, bottomId.schoolId); } @Override public int hashCode() { return Objects.hash(bId, cId, schoolId); } }
3. 优化User端的@OneToMany(可选但推荐)
虽然Bottom端配置好之后,User端的关联已经能正常工作,但为了让双向关联的映射关系更清晰,你可以给User的@OneToMany也补充上关联条件:
@IdClass(UserId.class) @Entity class User { @Id private String uId; @Id private String schoolId; @OneToMany(mappedBy="user") @JoinColumns({ @JoinColumn(name = "schoolId", referencedColumnName = "schoolId"), @JoinColumn(name = "cId", referencedColumnName = "uId") }) private List<Bottom> bottoms; }
这样配置完成后,Hibernate就不会再生成多余的user_uId和user_schoolId字段,而是直接用Bottom表中已有的schoolId和cId来关联User表,完全符合你要求的关联规则啦!
内容的提问来源于stack exchange,提问作者Baba
相关产品推荐
相关产品推荐

