JPA / Ruhezustand - Einbetten eines Attributs

8

Ich habe Probleme beim Zuordnen eines eingebetteten Attributs einer Klasse. Ich habe einige Klassen erstellt, die dem ähnlich sind, was ich zu illustrieren versuche. Grundsätzlich habe ich eine @ Embeddable Klassenhierarchie, die Vererbung verwendet. Die Top-Level-Klasse "Part Number" hat nur ein Attribut, und die Erweiterungsklassen fügen der Klasse "Part Number" keine Attribute hinzu, sie fügen nur einige Validierungen / Logik hinzu.

Hier ist was ich meine:

PART

%Vor%

PARTNUMMER

%Vor%

FORD PARTNUMBER

%Vor%

CHEVY PARTNUMBER

%Vor%

Natürlich funktioniert das nicht, weil Hibernate die Vererbungshierarchie ignoriert und die Tatsache, dass PartNumber abstrakt ist, nicht mag. Gibt es eine Möglichkeit, JPA- oder Hibernate-Anmerkungen zu verwenden? Ich habe versucht, die @Inheritance-JPA-Anmerkung zu verwenden.

Ich kann den "PartNumber" -Teil der Hierarchie nicht umgestalten, da der ursprüngliche Entwickler PartNumber um N viele XXXXPartNumber-Klassen erweitern möchte.

Weiß jemand, ob so etwas Teil der JPA 2.0 oder einer neuen Version von Hibernate sein wird?

    
systemoutprintln 13.07.2009, 14:11
quelle

5 Antworten

15

Die Vererbung von Komponenten (z. B. @Embeddable) wird nicht unterstützt und wird höchstwahrscheinlich nie sein. Dafür gibt es einen guten Grund - die Entitätskennung spielt eine wichtige Rolle in allen Vererbungsstrategien, die von Hibernate unterstützt werden, und Komponenten haben keine (zugeordneten) Identifikatoren.

Sie haben drei Möglichkeiten:

A) Teilenummer (und alle ihre Nachkommen) als Entitäten zuordnen. PartNumber kann abstrakt bleiben:

%Vor%

B) Basierend auf Ihrem Beispiel scheint es, dass alle PartNumber-Nachkommen sich nur im Verhalten unterscheiden (sie führen keine neuen Eigenschaften zum Speichern ein). Wenn das der Fall ist, können Sie PartNumber-Eigenschaften plus Ihren eigenen Diskriminatorwert (so dass Sie wissen, welche Klasse instanziiert wird) als @Embedded private -Eigenschaft zuordnen und get / setPartNumber () -Accessoren in der Part-Klasse marshall / unmarshall-geeignete Unterklassen haben. Sie können sogar Ihren eigenen benutzerdefinierten Hibernate-Typ schreiben, um das für Sie zu tun (es ist ziemlich einfach).

C) Wenn PartNumber-Nachkommen sich in Eigenschaften unterscheiden, die gespeichert werden müssen, und sie als Entitäten zuordnen, ist aus irgendeinem Grund inakzeptabel. Sie können marshall / unmarshall verwenden, um sie zu stringeln (als XML oder alles, was zur Rechnung passt) und zu speichern Das. Ich benutze XStream für diesen genauen Zweck und ich schrieb einen einfachen Hibernate-Typ, um damit zu gehen. Ihr Part-Mapping würde ungefähr wie

aussehen %Vor% Die Nachkommen von

und PartNumber müssen überhaupt nicht zugeordnet werden. Der Nachteil ist natürlich, dass der Umgang mit XML in der Datenbank ein bisschen mühsamer ist, so dass dies möglicherweise nicht der ideale Ansatz für etwas ist, über das Sie möglicherweise berichten müssten. OTOH, ich benutze dies zum Speichern von Plugin-Einstellungen und es hat mich viel Probleme mit Mappings / DB Wartung.

    
ChssPly76 17.07.2009, 05:50
quelle
2

Ich habe ein ähnliches Problem in meinem eigenen Schema, also ist das, worauf ich im Moment zurückgegriffen habe, so:

Elternklasse:

%Vor%

Kinderklassen:

%Vor%

Nun konnte ich dann den Biz-Key manipulieren, was ich auch brauchte, und das funktionierte gut, weil jeder der verschiedenen Teiletypen eine eigene Tabelle hatte (was für uns nützlich ist).

Sie könnten auch @Embedded mit @AttributeOverrides verwenden. Ich denke, die Spaltennamen anders zu spezifizieren, wie Sie es auch brauchen ... Es gibt ein Beispiel aus dem annotationsdokumente .

%Vor%

...

%Vor%

...

%Vor%

Sie können das vielleicht genug missbrauchen, dass es Ihnen egal ist ...

    
Petriborg 14.07.2009 19:38
quelle
1

Hmm, nicht sicher. Haben Sie versucht, @MappedSuperclasson PartNumber und @Embeddable zu setzen?  zu den Unterklassen. Siehe auch - Ссылка

Als Seitenknoten - haben Sie erwogen, Hibernate Validator anstelle der Validierungsmethode zu verwenden?

    
Hardy 13.07.2009 14:45
quelle
1

Es sieht so aus, als würden Sie "Embedable Inheritance" verwenden, was ich glaube, dass Hibernate noch nicht unterstützt wird.

%Vor%

Da sieht es so aus, als würde der diktierende Wert zwischen Ford und Chevy wie ein Format aussehen. Ich würde wahrscheinlich die Zuordnung ausblenden und eine andere Funktion hinzufügen, um den gewünschten Typ zurückzugeben.

%Vor%

Siehe die Links in den Kommentaren ...

    
ccclark 13.07.2009 21:58
quelle
0

Wie in anderen Antworten erwähnt, scheint Hibernate die Vererbung der eingebetteten Dateien nicht zu unterstützen (zumindest habe ich es nicht geschafft). Ich habe mir einige Workarounds ausgedacht (Danke @ ChssPly76 für die Inspiration):

1) Ersetzen Sie @Embaddable durch @Entity und speichern Sie die PartNumber Hierarchie in der dedizierten Tabelle. Natürlich muss @OneToOne relation mit der zusammengesetzten Klasse ( Part ) verwendet werden.

2) Führen Sie eine zwischengeordnete Entitätsklasse ein, die die Struktur der Datenbanktabelle vollständig widerspiegelt. Und dann ordnen Sie die Entität Ihren Domänenmodellklassen (und zurück) manuell zu. Dieser Ansatz bietet eine extreme Flexibilität zum Preis der manuellen Arbeit zum Schreiben und Testen von Mapping-Code.

3) Speichern Sie PartNumber Nachkommen in serialisierter Form und verlassen Sie sich auf Serializer, die in der Lage sein müssen, die richtige Klasse während der Deserialisierung instanziieren.

Für meine Aufgabe habe ich den dritten Ansatz gewählt. Ich verwende Hibernate-Typen , um Objekte in JSON zu serialisieren und das Ergebnis in jsonb Spalte des PostgreSQL. Hibernate-Typen verwenden Jackson unter der Haube, so dass alle ihre Anmerkungen (einschließlich derer, die polymorphes Verhalten steuern) zu Ihrer Verfügung stehen. In Ihrem Fall wäre der Code wie folgt:

%Vor%

Der resultierende JSON in der Datenbank sieht wie

aus %Vor%     
Lu55 06.12.2017 22:22
quelle