Hibernate:两个关系使用同一列作为外键

问题描述 投票:0回答:1

我正在开发一个需要支持文件夹树的简单版本控制系统的应用程序。本质上,这意味着用户可以创建包含不同文件夹的文件夹树。当他们满意时,他们可以保存这个版本,创建一个新版本并继续处理新版本(如果你愿意的话,这很像版本控制系统)。我的数据库架构目前如下所示:

CREATE TABLE IF NOT EXISTS folder
(
    id           INT         NOT NULL AUTO_INCREMENT,
    updated_at   TIMESTAMP   NOT NULL,
    created_at   TIMESTAMP   NOT NULL,
    PRIMARY KEY (id)
);

CREATE TABLE IF NOT EXISTS folder_version
(
    id              INT          NOT NULL AUTO_INCREMENT,
    version         INT          NOT NULL,
    folder_id       INT          NOT NULL,
    name            VARCHAR(255) NOT NULL,
    updated_at      TIMESTAMP    NOT NULL,
    created_at      TIMESTAMP    NOT NULL,
    PRIMARY KEY (id),
    UNIQUE KEY (folder_id, version),
    FOREIGN KEY (folder_id) REFERENCES folder (id)
);

CREATE TABLE IF NOT EXISTS folder_relation_version
(
    id         INT         NOT NULL AUTO_INCREMENT,
    parent_id  INT         NOT NULL,
    child_id   INT         NOT NULL,
    version    INT         NOT NULL,
    updated_at TIMESTAMP   NOT NULL,
    created_at TIMESTAMP   NOT NULL,
    PRIMARY KEY (id),
    UNIQUE KEY (parent_id, child_id, version),
    FOREIGN KEY (parent_id, version) REFERENCES folder_version (folder_id, version),
    FOREIGN KEY (child_id, version) REFERENCES folder_version (folder_id, version)
);

但是,我无法在 Hibernate 中为

folder_relation_version
表创建实体,因为
version
列同时用于两个外键约束。

具体的设计选择实际上是有意的,因为我想避免两个文件夹版本可以链接,当它们不属于同一版本时。

这意味着以下情况应该是可能的: 文件夹_A(版本=0)-->文件夹_B(版本=0)

但是这种情况应该是不可能的: 文件夹_A(版本=0)-->文件夹_B(版本=1)

下面是我当前的尝试,它至少可以编译,但显然插入和更新不适用于这种方法:

@Getter
@Setter
@SuperBuilder
@ToString
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
@Table(name = "folder_relation_version")
public class FolderRelationVersion extends BaseEntity {

    @Column(name = "version")
    private Integer version;

    @ManyToOne
    @JoinColumns({
            @JoinColumn(name = "parent_id", referencedColumnName = "folder_id", insertable = false, updatable = false),
            @JoinColumn(name = "version", referencedColumnName = "version", insertable = false, updatable = false)
    })
    private FolderVersion parent;

    @ManyToOne
    @JoinColumns({
            @JoinColumn(name = "child_id", referencedColumnName = "folder_id", insertable = false, updatable = false),
            @JoinColumn(name = "version", referencedColumnName = "version", insertable = false, updatable = false)
    })
    private FolderVersion child;
}

我现在的问题是:有没有办法在休眠中模拟这样的场景?或者这是否不是确保仅当属于同一版本的一部分时才链接FolderVersion 实体的正确方法。任何提示、想法或想法将不胜感激。

java sql database hibernate data-modeling
1个回答
0
投票

我找到了一个解决方案,适用于也偶然发现这个问题的人。

@Getter
@Setter
@SuperBuilder
@ToString
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
@Table(name = "folder_relation_version")
public class FolderRelationVersion extends BaseEntity {

    @Column(name = "version")
    private Integer version;

    @ManyToOne
    @JoinColumns({
            @JoinColumn(name = "parent_id", referencedColumnName = "folder_id", insertable = false, updatable = false),
            @JoinColumn(name = "version", referencedColumnName = "version", insertable = false, updatable = false)
    })
    private FolderVersion parent;

    @ManyToOne
    @JoinColumns({
            @JoinColumn(name = "child_id", referencedColumnName = "folder_id", insertable = false, updatable = false),
            @JoinColumn(name = "version", referencedColumnName = "version", insertable = false, updatable = false)
    })
    private FolderVersion child;

    @Column(name = "child_id")
    private Integer childId;


    @Column(name = "parent_id")
    private Integer parentId;

    public void setChild(FolderVersion child) {
        this.child = child;
        this.childId = child.getFolderId();
    }

    public void setParent(FolderVersion parent) {
        this.child = parent;
        this.childId = parent.getFolderId();
    }
}

显然,每当您设置实体时,您只需显式添加 id 字段并设置它们,以便数据库插入工作。

© www.soinside.com 2019 - 2024. All rights reserved.