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

Hibernate复合主键外键重叠保存时bank_id非空约束报错如何解决

问题根因

你触发异常的核心原因是BonusEntity的关联注解配置错误:

  • 你给关联AccountEntity的三个@JoinColumn全部设置了insertable = false, updatable = false,意味着Hibernate在插入数据时不会处理这三个外键字段的写入
  • 其中cluster_id属于BonusEntity的复合主键,所以插入时会自动赋值,但bank_id、user_id没有任何对应字段负责写入,自然就是NULL,触发数据库非空约束
解决方案

你只需要调整关联注解的配置,仅保留主键重叠字段cluster_id的insertable = false, updatable = false配置,剩下两个外键字段放开写入权限即可,Hibernate会自动从关联的AccountEntity主键中提取对应值写入表中:

调整后的BonusEntity代码示例:

@Entity
@Table(name = "cbonus")
public class BonusEntity {
    @EmbeddedId
    @AttributeOverride(name = "id", column = @Column(name = "id"))
    @AttributeOverride(name = "clusterId", column = @Column(name = "cluster_id"))
    private BonusId bonusId;
    private boolean released;
    
    @ManyToOne(targetEntity = AccountEntity.class, optional = false, fetch = FetchType.LAZY)
    @JoinColumn(name = "cluster_id", referencedColumnName = "cluster_id", insertable = false, updatable = false)
    // 去掉bank_id、user_id对应的insertable、updatable禁用配置
    @JoinColumn(name = "bank_id", referencedColumnName = "bank_id")
    @JoinColumn(name = "user_id", referencedColumnName = "user_id")
    private AccountEntity account;
}
补充注意事项

如果你的业务场景需要单独访问bank_id、user_id字段不需要加载整个AccountEntity,也可以在BonusEntity中显式定义这两个字段,再调整关联注解的配置关联到这两个字段即可:

@Entity
@Table(name = "cbonus")
public class BonusEntity {
    @EmbeddedId
    @AttributeOverride(name = "id", column = @Column(name = "id"))
    @AttributeOverride(name = "clusterId", column = @Column(name = "cluster_id"))
    private BonusId bonusId;
    
    @Column(name = "bank_id", nullable = false)
    private Long bankId;
    @Column(name = "user_id", nullable = false)
    private String userId;
    
    private boolean released;
    
    @ManyToOne(targetEntity = AccountEntity.class, optional = false, fetch = FetchType.LAZY)
    @JoinColumn(name = "cluster_id", referencedColumnName = "cluster_id", insertable = false, updatable = false)
    @JoinColumn(name = "bank_id", referencedColumnName = "bank_id", insertable = false, updatable = false)
    @JoinColumn(name = "user_id", referencedColumnName = "user_id", insertable = false, updatable = false)
    private AccountEntity account;
    
    // 自定义setAccount方法自动同步bankId、userId字段
    public void setAccount(AccountEntity account) {
        this.account = account;
        this.bankId = account.getAccountId().getBankId();
        this.userId = account.getAccountId().getUserId();
    }
}

使用这种方案时,保存BonusEntity前调用setAccount方法即可自动完成字段同步,不需要手动赋值两个外键字段。

内容的提问来源于stack exchange,提问作者Vasiliy Tungusov

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 21:18:03