具有重叠复合主键和外键的休眠

HIBERNATE with overlapping composite PRIMARY and FOREIGN KEYs

我有一些实体:

@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)
    @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;
}

@Entity
@Table(name = "account")
public class AccountEntity {

    @EmbeddedId
    @AttributeOverride(name = "clusterId", column = @Column(name = "cluster_id"))
    @AttributeOverride(name = "bankId", column = @Column(name = "bank_id"))
    @AttributeOverride(name = "userId", column = @Column(name = "user_id"))
    @NotNull
    private AccountId accountId;

    // other fields
}

当我尝试保存新的 cbonus 记录时出现异常:

org.postgresql.util.PSQLException: ERROR: null value in column "bank_id" of relation "cbonus" violates not-null constraint Detail: Failing row contains (773, gp3, null, null, f).

并查询

DEBUG 24817 --- [nio-8080-exec-4] org.hibernate.SQL
: insert into cbonus (released, cluster_id, id) values (?, ?, ?)

就在保存之前,对象的所有字段都已填充。 我试图删除空值约束,但是这些值只是保持为 NULL。我认为原因是复合主键和复合外键重叠。

我如何使用 Hibernate 来管理它?

数据库模式:

CREATE TABLE cbonus
(
    id         BIGINT                NOT NULL,
    cluster_id TEXT                  NOT NULL,
    bank_id    BIGINT                NOT NULL,
    user_id    TEXT                  NOT NULL,
    released   BOOLEAN DEFAULT FALSE NOT NULL,
    FOREIGN KEY (cluster_id, bank_id, user_id) REFERENCES account,
    PRIMARY KEY (id, cluster_id)
);

CREATE TABLE account
(
    cluster_id TEXT       NOT NULL,
    bank_id    BIGINT     NOT NULL,
    user_id    TEXT       NOT NULL,
    -- [other fields]
    PRIMARY KEY (cluster_id, bank_id, user_id)
);

你的映射有误。根据您的设置,bank_id 列从不“可写”。你需要这个:

    @AttributeOverride(name = "id", column = @Column(name = "id"))
    @AttributeOverride(name = "clusterId", column = @Column(name = "pk_cluster_id"))
    private BonusId bonusId;

    @ManyToOne(targetEntity = AccountEntity.class, optional = false, fetch = FetchType.LAZY)
    @JoinColumnsOrFormulas({
       @JoinColumnOrFormula(column = @JoinColumn(name = "bank_id", referencedColumnName = "bank_id")),
       @JoinColumnOrFormula(column = @JoinColumn(name = "user_id", referencedColumnName = "user_id")),
       @JoinColumnOrFormula(formula = @JoinFormula(value = "cluster_id", referencedColumnName = "cluster_id"))
    private AccountEntity account;

    })

和一些架构修复:

CREATE TABLE command_response
(
    id                   BIGSERIAL PRIMARY KEY,
    pk_cluster_id        TEXT                    NOT NULL,
    cluster_id           TEXT                    NOT NULL,
    bank_id              BIGINT                  NOT NULL,
    ...
    FOREIGN KEY (cluster_id, bank_id, user_id) REFERENCES account,
    PRIMARY KEY (id, pk_cluster_id)