Вопрос по hibernate, one-to-many, java – Hibernate отношения «многие к одному» без первичного ключа или таблицы соединений

16
проблема

Я хотел бы начать с того, что я понимаю, что структура базы данных ужасна, но я не могу изменить ее в данный момент.

При этом мне нужно создать двунаправленное отношение «один ко многим» в 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)
Джава

GlobalPart.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 releases;

    public Long getGlobalPartId() {
        return globalPartId;
    }

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

    public Set getReleases() {
        return releases;
    }

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

}

PartRelease.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;
    }

}

Любая помощь будет принята с благодарностью!

Ваш Ответ

2   ответа
1

Как объяснено вЭта статьявсякий раз, когда вам нужно отобразить@ManyToOne используя столбец без первичного ключа на родительской стороне, вы должны использоватьreferencedColumnName атрибут@JoinColumn аннотаций.

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

я использовалFetchType.LAZY для@ManyToOne потому что по умолчанию используется выборка EAGER, котораяочень плохо для производительности.

29

в двунаправленной ассоциации всегда есть сторона владельца, которая определяет отображение, и обратная сторона, отмеченная наличиемmappedBy приписывать.

В ассоциации OneToMany сторона владельца всегда является стороной многих (PartRelease в вашем случае).

Кроме того, столбец соединения по умолчанию ссылается на идентификатор объекта, на который он ссылается. С тех пор'Это не то, что вы хотите, вы должны указать имя столбца, на который указывает ссылка.

И, конечно, столбец 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;

}
</partrelease>

Ассоциации хорошо описаны вдокументация, Вы должны прочитать это.

Отлично! Спасибо вам большое! Я изначально прошел этот путь, но я скучал поreleaseNumber свойство сопоставлено сRELEASES колонка. В конце концов я убедил себя, что я делаю это неправильно (неправильно читая MappingException) и принял подход, упомянутый в вопросе. Еще раз спасибо! chrismborland

Похожие вопросы