2010-09-29 8 views
29

J'ai une base de données avec la structure suivante:entité JPA sans id

CREATE TABLE entity (
    id SERIAL, 
    name VARCHAR(255), 
    PRIMARY KEY (id) 
); 

CREATE TABLE entity_property (
    entity_id SERIAL, 
    name VARCHAR(255), 
    value TEXT 
); 

Lorsque je tente 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; 
    } 
} 

-je obtenir 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 base de données pour des raisons qui sont au-delà de mes cont rol. 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?

Répondre

32

Je suppose que votre entity_property a une (entity_id, name) clé composite où entity_id est une clé étrangère à entity. Si oui, vous pouvez 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; 

    ... 
} 
+1

Merci. Mais comment puis-je accéder directement à la propriété "name" de l'entité dans ce cas? Ma requête JP-QL ne fonctionne bien que si l'accès à "name" via "entity.id.name", mais je pense que ce n'est pas correct. – mikhail

+0

@mikhail: Si vous n'aimez pas l'approche avec '@ EmbeddedId', vous pouvez essayer une approche alternative avec' @ IdClass': http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/#d0e1112 – axtavt

+4

L'annotation pour 'EntityPropertyPK' devrait-elle être' @ Embeddedable' au lieu de '@ Embedded'? – HDoan

2

Je suppose que vous pouvez utiliser @CollectionOfElements (pour mise en veille prolongée/JPA 1)/@ElementCollection (JPA 2) pour mapper une collection de "propriétés de l'entité" à un List dans entity.

Vous pouvez créer le type EntityProperty et annoter avec @Embeddable

0

S'il y a un à un entre les entités et entity_property vous pouvez utiliser entity_id comme identifiant.

22

Je sais que les entités JPA doivent avoir la clé primaire, mais je ne peux pas changer la structure de base de données pour des raisons indépendantes de ma volonté.

Plus précisément, une entité JPA doit avoir certaines Id définies. Mais une JPA Id ne doit pas nécessairement être mappée sur la clé primaire de la table (et JPA peut en quelque sorte traiter avec une table sans une clé primaire ou une 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 la table qui rend une valeur unique, vous pouvez utiliser cet ensemble unique de colonnes que votre Id JPA.

Si votre table ne contient aucune colonne unique, vous pouvez utiliser toutes les colonnes comme Id.

Et si votre table contient un ID, mais pas votre entité, attribuez-lui la valeur Embeddable.

10

Voir la Java Persistence livre: Identity and Sequencing

La partie pertinente de votre question est le No Primary Key section:

Parfois, votre objet ou d'une table n'a pas de clé primaire. La meilleure solution dans ce cas consiste normalement à ajouter un ID généré à l'objet et une table .Si vous ne disposez pas de cette option, il existe parfois une colonne ou un ensemble de colonnes qui constituent une valeur unique. Vous pouvez utiliser cet ensemble unique de colonnes comme ID dans JPA. L'Assemblée parlementaire paritaire Id n'a pas toujours correspondre à la table de base de données principale contrainte clé, ni est une clé primaire ou une contrainte unique nécessaire.

Si votre table a vraiment pas de colonnes uniques, utilisez toutes les colonnes comme id. En général, lorsque cela se produit, les données sont en lecture seule, même si la table permet des lignes en double avec les mêmes valeurs, les objets sera le même de toute façon, il n'a pas d'importance que JPA pense qu'ils sont le même objet. Le problème avec les mises à jour permettant et supprime est qu'il n'y a aucun moyen d'identifier de manière unique la ligne de l'objet, de sorte que tous les lignes correspondantes seront mises à jour ou supprimés.

Si votre objet ne dispose pas d'un identifiant, mais sa table fait, cela est très bien. Rendre l'objet objet Embeddable, les objets incorporables ne possèdent pas d'ID. Vous aurez besoin d'un Entity qui contient ce Embeddable pour persister et interroger.

+0

Wow c'était super perspicace. Merci d'avoir partagé. – comiventor

+0

C'est ce que je cherchais, merci! – lloiacono