J'ai une base de données avec la structure suivante:
CREATE TABLE entity (
id SERIAL,
name VARCHAR(255),
PRIMARY KEY (id)
);
CREATE TABLE entity_property (
entity_id SERIAL,
name VARCHAR(255),
value TEXT
);
Lorsque j'essaie de créer une classe EntityProperty
@Entity
@Table(name="entity_property")
public class EntityProperty {
private String name;
private String value;
@Column(name="name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Column(name="value", nullable=true, length=255)
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
J'obtiens l'exception suivante:
org.hibernate.AnnotationException: No identifier specified for entity: package.EntityProperty
Je sais que les entités JPA doivent avoir une clé primaire mais je ne peux pas modifier le schéma de la base de données pour des raisons indépendantes de ma volonté. Est-il possible de créer des entités JPA (Hibernate) qui fonctionneront avec un schéma de base de données comme celui-ci?
Je suppose que votre entity_property
possède une clé composite (entity_id, name)
où entity_id
est une clé étrangère pour entity
. Si oui, vous pouvez le mapper comme suit:
@Embeddable
public class EntityPropertyPK {
@Column(name = "name")
private String name;
@ManyToOne
@JoinColumn(name = "entity_id")
private Entity entity;
...
}
@Entity
@Table(name="entity_property")
public class EntityProperty {
@EmbeddedId
private EntityPropertyPK id;
@Column(name = "value")
private String value;
...
}
Je sais que les entités JPA doivent avoir une clé primaire mais je ne peux pas changer la structure de la base de données pour des raisons indépendantes de ma volonté.
Plus précisément, une entité JPA doit avoir un Id
défini. Mais un JPA Id
ne doit pas nécessairement être mappé sur la clé primaire de la table (et JPA peut en quelque sorte traiter une table sans clé primaire ni contrainte unique).
Est-il possible de créer des entités JPA (Hibernate) qui fonctionneront avec une structure de base de données comme celle-ci?
Si vous avez une colonne ou un ensemble de colonnes dans le tableau qui crée une valeur unique, vous pouvez utiliser cet ensemble unique de colonnes comme Id
dans JPA.
Si votre table ne contient aucune colonne unique, vous pouvez utiliser toutes les colonnes comme Id
.
Et si votre table a un identifiant mais pas votre entité, faites-en un Embeddable
.
Voir le livre Java Persistence : Identity and Sequencing
La partie pertinente pour votre question est la Pas de section Clé primaire :
Parfois, votre objet ou votre table n'a pas de clé primaire. La meilleure solution dans ce cas est normalement d'ajouter un identifiant généré à l'objet et à la table. Si vous ne disposez pas de cette option, il existe parfois une colonne ou un ensemble de colonnes dans le tableau qui constituent une valeur unique. Vous pouvez utiliser cet ensemble unique de colonnes comme identifiant dans JPA. Le JPA
Id
ne doit pas toujours correspondre à la contrainte de clé primaire de la table de base de données, et aucune clé primaire ou contrainte unique n'est requise.Si votre table n'a vraiment aucune colonne unique, utilisez toutes les colonnes comme identifiant. Généralement, lorsque cela se produit, les données sont en lecture seule, donc même si le tableau autorise les lignes en double avec les mêmes valeurs, les objets seront de toute façon les mêmes, donc peu importe que JPA pense qu'ils sont le même objet. Le problème avec l'autorisation des mises à jour et des suppressions est qu'il n'y a aucun moyen d'identifier de manière unique la ligne de l'objet, donc toutes les lignes correspondantes seront mises à jour ou supprimées.
Si votre objet n'a pas d'identifiant, mais que sa table en a, c'est bien. Faites de l'objet un objet
Embeddable
, les objets intégrables n'ont pas d'identifiant. Vous aurez besoin d'unEntity
qui contient ceEmbeddable
pour persister et l'interroger.
Je suppose que vous pouvez utiliser @CollectionOfElements
(pour l'hibernation/jpa 1)/ @ElementCollection
(jpa 2) pour mapper une collection de "propriétés d'entité" à un List
dans entity
.
Vous pouvez créer le type EntityProperty
et l'annoter avec @Embeddable
S'il existe un mappage un à un entre entité et property_property, vous pouvez utiliser entity_id comme identifiant.