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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:52:13