2010-09-29 17 views
29

Ich habe eine Datenbank mit der folgenden Struktur:JPA-Entität ohne id

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

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

Wenn ich versuche, eine EntityProperty Klasse erstellen

@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; 
    } 
} 

Ich erhalte die folgende Ausnahme:

org.hibernate.AnnotationException: No identifier specified for entity: package.EntityProperty 

Ich weiß, dass JPA-Entitäten einen Primärschlüssel haben müssen, aber ich kann das Datenbankschema aus Gründen, die außerhalb meines Kontos liegen, nicht ändern rol. Ist es möglich JPA (Hibernate) -Entitäten zu erstellen, die mit einem solchen Datenbankschema arbeiten?

Antwort

32

Ich denke, Ihre entity_property hat einen zusammengesetzten Schlüssel (entity_id, name), wobei entity_id ein Fremdschlüssel zu entity ist. Wenn ja, können Sie es Karte wie folgt:

@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

Danke. Aber wie kann ich in diesem Fall direkt auf die Entität "name" zugreifen? Meine JP-QL-Abfrage funktioniert nur gut, wenn ich über "entity.id.name" auf "name" zugreife, aber ich denke, dass das nicht stimmt. – mikhail

+0

@mikhail: Wenn Sie Ansatz mit '@ EmbeddedId' nicht mögen, können Sie alternativen Ansatz mit' @ IdClass' versuchen: http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/#d0e1112 – axtavt

+4

Sollte die Annotation für 'EntityPropertyPK' '@ Embeddedable' statt' @ Embedded' sein? – HDoan

2

Ich denke, man @CollectionOfElements verwenden kann (Hibernate/JPA 1)/@ElementCollection (JPA 2) eine Sammlung von "Elementeigenschaften" zur Karte zu einem List in entity.

können Sie erstellen die EntityProperty Typ und mit Anmerkungen versehen es mit @Embeddable

0

Wenn es eine Eins-zu-Eins-Abbildung zwischen Einheit und entity_property ist Sie ENTITY_ID als Kennung verwenden können.

22

Ich weiß, dass JPA-Entitäten Primärschlüssel haben muss, aber ich kann nicht die Datenbankstruktur aus Gründen, die außerhalb meiner Kontrolle ändern.

Genauer gesagt muss eine JPA-Entität einige Id definiert haben. Aber eine JPA Id muss nicht unbedingt auf den Primärschlüssel der Tabelle abgebildet werden (und JPA kann irgendwie mit einer Tabelle ohne Primärschlüssel oder eindeutige Einschränkung umgehen).

Ist es möglich JPA (Hibernate) -Entitäten zu erstellen, die mit einer Datenbankstruktur wie dieser arbeiten?

Wenn Sie eine Spalte oder eine Gruppe von Spalten in der Tabelle, die einen eindeutigen Wert macht, können Sie diese einzigartige Reihe von Spalten als Id in JPA verwenden. Wenn Ihre Tabelle keine eindeutigen Spalten enthält, können Sie alle Spalten als Id verwenden.

Und wenn Ihre Tabelle eine ID hat, aber Ihre Entität nicht, machen Sie sie zu Embeddable.

10

Siehe Java Persistence Buch: Identity and Sequencing

Der relevante Teil für Ihre Frage ist die No Primary Key section:

Manchmal hat Ihr Objekt oder Tabelle keinen Primärschlüssel. Die beste Lösung in diesem Fall ist normalerweise eine generierte ID zum Objekt und Tabelle hinzuzufügen.Wenn Sie diese Option nicht haben, gibt es manchmal eine Spalte oder Spalten in der Tabelle, die einen eindeutigen Wert bilden. Sie können diesen eindeutigen Satz von Spalten als Ihre ID in JPA verwenden. Die JPA Id muss nicht immer dem Zwang der Primärschlüssel der Datenbanktabelle entsprechen, noch ist ein Primärschlüssel oder eine eindeutige Einschränkung erforderlich. Wenn Ihre Tabelle wirklich keine eindeutigen Spalten hat, dann verwenden Sie alle Spalten als die ID. In diesem Fall sind die Daten normalerweise schreibgeschützt. Wenn die Tabelle also doppelte Zeilen mit denselben Werten zulässt, sind die Daten schreibgeschützt, so dass die Objekte trotzdem gleich sind. Es ist also egal, dass JPA denkt, dass sie das gleiche Objekt sind. Das Problem mit Aktualisierungen und Löschungen ist , dass es keine Möglichkeit gibt, die Zeile des Objekts eindeutig zu identifizieren, so dass alle die übereinstimmenden Zeilen aktualisiert oder gelöscht werden.

Wenn Ihr Objekt keine ID hat, aber seine Tabelle, ist das in Ordnung. Machen Sie das Objekt zu einem Embeddable Objekt, einbettbare Objekte haben keine IDs. Sie benötigen eine Entity, die enthält diese Embeddable Persistenz und Abfrage.

+0

Wow, das war super aufschlussreich. Danke für das Teilen. – comiventor

+0

Dies ist, was ich gesucht habe, danke! – lloiacono