2010-09-15 5 views
5

Können wir mit JPA eine enum als ID einer Entität definieren?Verwendung von enum als ID

Ich habe versucht, die folgenden:

public enum AssetType { 
    .... 
} 

@Entity 
@IdClass(AssetType.class) 
public class Adkeys { 

    private AssetType type; 

    @Id 
    @Enumerated(EnumType.STRING) 
    @Column(nullable = false) 
    public AssetType getType() { 
     return type; 
    } 

} 

Mit OpenJPA, es klagt:

org.apache.openjpa.persistence.ArgumentException: Die ID-Klasse "Klasse aa.AssetType" angegeben nach Typ "Klasse aa.Adkeys" hat keinen öffentlichen No-Args-Konstruktor.

Also meine Fragen sind:

  • sollten wir in der Lage Enum als ID für eine Entität auf PPV benutzen? (d. h., es gibt einen Fehler in OpenJPA)
  • oder mache ich irgendwo einen Fehler?
  • und gibt es eine Problemumgehung für ein solches Problem?
+0

@Nathan: Also dann muss es ein Fehler sein. –

Antwort

7

Die JPA-Spezifikation nicht sagen, dies ist möglich:

2.1.4 Primärschlüssel und Entity Identität

Der Primärschlüssel (oder Feld oder eine Eigenschaft eines zusammengesetzten Primärschlüssels) soll einer der folgenden Typen sein: jeder Java-Primitivtyp; irgendein primitiver Wrappertyp; java.lang.String; java.util.Datum; java.sql.Datum. Im Allgemeinen sollten jedoch ungefähre numerische Typen (z. B. Fließkommatypen) niemals in Primärschlüsseln verwendet werden. Entitäten, deren Primärschlüssel andere Typen als diese verwenden, sind nicht tragbar.

Wenn Sie wirklich eine Kompilierung-feste Anzahl von Datensätzen für eine bestimmte Person haben wollen, können Sie eine String oder int Primärschlüssel verwenden und es AssetType.FOO.name() oder AssetType.FOO.ordinal()

Und nicht tragbaren hier Mittel zuweisen dass ein bestimmter Persistenzanbieter andere Dinge unterstützt, aber möglicherweise nicht für einen anderen Anbieter funktioniert. Wie bei der Enumeration - wenn der Persistenzprovider eine spezielle Unterstützung dafür hat, versucht es nicht, es zu instanziieren, sondern verarbeitet es speziell nach der Überprüfung von class.isEnum(), dann könnte es funktionieren. Aber es scheint, dass Ihr Persistenzanbieter dies nicht tut.

+0

Es heißt nicht, dass dies möglich ist, aber es ist auch nicht unmöglich. Es sagt nur: "Entitäten, deren Primärschlüssel andere Typen als diese verwenden, sind nicht tragbar." In der Tat heißt es nicht, dass eine Klasse als Primärschlüssel verwendet werden kann, aber es ist möglich. – nanda

+0

das ist eine andere Sache - eine einbettbare ID. Siehe mein Update für den Portabilitätsteil. – Bozho

+0

also denke ich, das ist eine gültige Anfrage für eine Erweiterung, meinst du nicht? – nanda

4

Nein, Sie können nicht Aufzählungen als ID verwenden, da JPA Ihr eigenes Mapping für ID-Spalten nicht erlaubt, zu definieren (sie int oder long oder etwas sein muss, die JPA mit new anlegen zu können).

IDs dürfen nicht der Geschäftsschlüssel sein (in Ihrem Fall: der Typ). Die Verwendung des Geschäftsschlüssels als ID ist ein häufiger Fehler in DB-Entwürfen und sollte vermieden werden, da später alle Arten von Problemen auftreten.

Fügen Sie eine unabhängige ID-Spalte hinzu, um das Problem zu lösen.

+0

Ich arbeite mit alten Datenbank. Es ist vielleicht kein gutes Design, aber es ist da. Das Enum ist nur ein Haufen starrer Werte. – nanda

0

Wollen Sie das wirklich tun? Dieses Konstrukt erlaubt es nicht, die Datenbank-Enum-Schlüssel zu ändern, ohne die Enumeration im Code zu aktualisieren (fehlgeschlagen beim Laden), und auch nicht umgekehrt (Constraint-Fehler). Warum erstellen Sie nicht einfach eine AssetType-Tabelle mit int pk und name und sorgen dafür, dass die Adkeys einen Fremdschlüssel für AssetType.id als pk haben?

Sie können die AssetTypes beim Start aus der Datenbank laden, wenn Sie sie in Ihrer App aufzählen müssen.

+0

Ich arbeite mit alten Datenbank. Natürlich kann ich es ändern, aber es könnte problematisch sein. Das Enum ist nur ein Haufen starrer Werte. – nanda