休眠多对一关系,不带主键或联接表

2022-09-02 09:03:44

问题

我想首先说,我意识到数据库结构是残酷的,但我现在无法改变它。

话虽如此,我需要在Hibernate(4.2.1)中创建一个一对多的双向关系,该关系不涉及主键(仅涉及关系的“父”端的唯一键)和连接表。表示此关系的外键是从“子”到“父”的后退点(见下文)。我已经搜索并尝试了各种不同的注释配置,但没有运气。我所要求的可能吗?

数据库

GLOBAL_PART

CREATE TABLE "GLOBAL_PART" (    
    "GLOBAL_PART_ID" NUMBER NOT NULL,
    "RELEASES" NUMBER,
    CONSTRAINT "GLOBAL_PART_PK" PRIMARY KEY ("GLOBAL_PART_ID"),
    CONSTRAINT "GLOBAL_PART_RELEASES_UK" UNIQUE ("RELEASES")
);

PART_RELEASE

CREATE TABLE "PART_RELEASE" (
    "PART_RELEASE_ID" NUMBER NOT NULL,
    "COLLECTION_ID" NUMBER,
    CONSTRAINT "PART_RELEASE_PK" PRIMARY KEY ("PART_RELEASE_ID"),
    CONSTRAINT "GLOBAL_PART_RELEASE_FK" FOREIGN KEY ("COLLECTION_ID")
        REFERENCES "GLOBAL_PART" ("RELEASES") ON DELETE CASCADE ENABLE
);

参考:

PART_RELEASE                 GLOBAL_PART
-------------------          ------------
PART_RELEASE_ID (PK)         GLOBAL_PART_ID (PK)
COLLECTION_ID -------------> RELEASES (UK)

爪哇岛

全球部分.java

@Entity
@Table(name = "GLOBAL_PART")
@SequenceGenerator(name = "SEQUENCE_GENERATOR", sequenceName = "GLOBAL_PART_SEQ")
public class GlobalPart extends ModelBase implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @Column(name = "GLOBAL_PART_ID", unique = true, nullable = false)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQUENCE_GENERATOR")
    private Long globalPartId;

    @OneToMany(fetch = FetchType.EAGER)
    @JoinColumn(name = "COLLECTIONGID")
    private Set<PartRelease> releases;

    public Long getGlobalPartId() {
        return globalPartId;
    }

    public void setGlobalPartId(Long globalPartId) {
        this.globalPartId = globalPartId;
    }

    public Set<PartRelease> getReleases() {
        return releases;
    }

    public void setReleases(Set<PartRelease> releases) {
        this.releases = releases;
    }

}

部件发布.java

@Entity
@Table(name = "PART_RELEASE")
@SequenceGenerator(name = "SEQUENCE_GENERATOR", sequenceName = "PART_RELEASE_SEQ")
public class PartRelease extends ModelBase implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @Column(name = "PART_RELEASE_ID", unique = true, nullable = false)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQUENCE_GENERATOR")
    private String partReleaseId;

    @ManyToOne
    @JoinColumn(name = "RELEASES")
    private GlobalPart globalPart;

    public String getPartReleaseId() {
        return partReleaseId;
    }

    public void setPartReleaseId(String partReleaseId) {
        this.partReleaseId = partReleaseId;
    }

    public GlobalPart getGlobalPart() {
        return globalPart;
    }

    public void setGlobalPart(GlobalPart globalPart) {
        this.globalPart = globalPart;
    }

}

任何帮助将不胜感激!


答案 1

首先,在双向关联中,总是有一个所有者端,它定义了映射,还有一个逆端,由属性的存在来标记。mappedBy

在OneToMany协会中,所有者一方始终是多方(在您的情况下,PartRelease)。

此外,默认情况下,联接列引用它所引用的实体的 ID。由于它不是您想要的,因此必须指定引用的列名称。

当然,必须映射 RELEASES 列:

public class GlobalPart extends ModelBase implements Serializable {

    @OneToMany(fetch = FetchType.EAGER, mappedBy = "globalPart")
    private Set<PartRelease> partReleases;

    @Column(name = "RELEASES")
    private Long releasesNumber;
}

public class PartRelease extends ModelBase implements Serializable {
    @ManyToOne
    @JoinColumn(name = "COLLECTION_ID", referencedColumnName = "RELEASES")
    private GlobalPart globalPart;

}

文档中很好地描述了关联。你应该阅读它。


答案 2

每当需要使用父端的非主键列映射@ManyToOne时,都必须使用批注的属性。referencedColumnName@JoinColumn

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(
    name = "RELEASES", 
    referencedColumnName = "COLLECTIONGID"
)

我之所以使用,是因为默认情况下,使用 FetchType.EAGER fetching,这对性能非常不利。FetchType.LAZY@ManyToOne


推荐