Je voudrais commencer par dire que je me rends compte que la structure de la base de données est atroce, mais je ne peux pas la changer pour le moment.
Cela étant dit, j'ai le besoin de créer une relation un-à-plusieurs et bidirectionnelle dans Hibernate (4.2.1) qui n'implique aucune clé primaire (seulement une clé unique du côté "parent" de la relation) et aucune joindre des tables. La clé étrangère représentant cette relation est un pointeur de "l'enfant" au "parent" (voir ci-dessous). J'ai cherché et essayé différentes configurations d'annotations différentes sans succès. Est-ce que ce que je demande est possible?
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
);
Référence:
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<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;
}
}
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;
}
}
Toute aide serait grandement appréciée !!
Tout d'abord, dans une association bidirectionnelle, il y a toujours un côté propriétaire, qui définit le mappage, et un côté inverse, marqué par la présence de l'attribut mappedBy
.
Dans une association OneToMany, le côté propriétaire est toujours le côté multiple (PartRelease dans votre cas).
De plus, une colonne de jointure, par défaut, fait référence à l'ID de l'entité qu'elle référence. Comme ce n'est pas ce que vous voulez, vous devez spécifier le nom de la colonne référencée.
Et bien sûr, la colonne RELEASES doit être mappée:
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;
}
Les associations sont bien décrites dans la documentation . Tu devrais le lire.
Comme expliqué dans cet article , chaque fois que vous devez mapper un @ManyToOne
en utilisant une colonne de clé non primaire du côté parent, vous devez utiliser l'attribut referencedColumnName
de @JoinColumn
annotation.
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(
name = "RELEASES",
referencedColumnName = "COLLECTIONGID"
)
J'ai utilisé FetchType.LAZY
pour le @ManyToOne
car par défaut, la récupération EAGER est utilisée, ce qui est très mauvais pour les performances .