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?
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 vonund 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.
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%Sie können das vielleicht genug missbrauchen, dass es Ihnen egal ist ...
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 ...
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:
Der resultierende JSON in der Datenbank sieht wie
aus %Vor%Tags und Links java jpa hibernate java-ee nhibernate