Ich verwende Hibernate als Persistenz-Layer. Es gibt 2 Entitäten, die in derselben Tabelle leben und eine Superklasse mit einer Vererbungsstrategie für einzelne Tabellen erweitern.
%Vor%Ich habe eine Instanz von B mit id = 4. Wie ändere ich den Typ dieser Instanz zu C unter Beibehaltung ihrer ID (4)?
%Vor%Der obige Code schlägt mit
fehl %Vor%Ist das überhaupt möglich?
Hibernate versucht, die Persistenz so transparent wie möglich zu machen - was bedeutet, dass er versucht, denselben Prinzipien zu folgen wie normale Java-Objekte. Wenn Sie nun Ihre Frage in Java neu formulieren, erhalten Sie:
Wie kann ich eine Instanz der B-Klasse in eine Instanz der (inkompatiblen) C-Klasse konvertieren?
Und Sie wissen die Antwort darauf - Sie können nicht. Sie können eine neue Instanz von C erstellen und notwendige Attribute kopieren, aber B wird immer B sein, niemals C. Die Antwort auf Ihre ursprüngliche Frage lautet also - es kann nicht gemacht werden über JPA oder Hibernate API.
Im Gegensatz zu einfachem Java kann man bei Hibernate jedoch mogeln :-) InheritanceType.SINGLE_TABLE
wird mit @DiscriminatorColumn
gemappt und um B in C zu konvertieren, muss man seinen Wert von dem für B spezifizierten in den für C spezifizierten Wert ändern Der Trick ist - Sie können es nicht mit der Hibernate API machen; Sie müssen es über Plain SQL tun. Sie können diese Aktualisierungsanweisung jedoch als benannte SQL-Abfrage zuordnen und mithilfe von Hibernate-Funktionen ausführen.
Der Algorithmus lautet daher:
In diesem Fall ist "c" ein Objekt, von dem die Hibernation-Sitzung nichts weiß, aber es hat eine ID, so dass angenommen wird, dass das Objekt bereits persistent ist. In diesem Zusammenhang macht persist () keinen Sinn, und so scheitert es.
Das Javadoc für Hibernate Session.persist () (Ich weiß, dass Sie nicht die Hibernate-API verwenden, aber die Semantik ist die gleiche, und die Hibernate-Dokumentation ist besser) sagt "Machen Sie eine vorübergehende Instanz persistent". Wenn Ihr Objekt bereits eine ID hat, ist es nicht vorübergehend. Stattdessen wird davon ausgegangen, dass es sich um eine getrennte Instanz handelt (d. H. Eine Instanz, die zwar beibehalten wurde, aber nicht mit der aktuellen Sitzung verknüpft ist).
Ich schlage vor, dass Sie merge () anstelle von persist () versuchen.
Sie können Ihre eigene ID verwenden (nicht generiert) und folgendermaßen vorgehen:
Auf diese Weise werden Sie die ID aus der Tabelle löschen, bevor Sie sie erneut als C einfügen.
Wie unterscheiden Sie zwischen den beiden Entitäten in der Tabelle? Ich nehme an, dass es einige Feldwerte (oder Werte) gibt, die Sie ändern können, um B zu einem C zu machen?
Sie könnten eine Methode haben, bei der Sie die Superklasse A laden und die Unterscheidungswerte ändern und speichern. Dann wird dein B in deiner nächsten Hibernate Session ein C sein.
Ich denke, Skaffman ist genau hier, sobald die ID gesetzt wurde, wird es nicht mehr bestehen, und außerdem, weil die ID erzeugt wird, erwartet sie, dass die Sequenz für die Zuweisung der ID-Nummer zuständig ist.
Sie könnten die ID möglicherweise nicht als @GeneratedValue angeben? oder einer der verschiedenen Generaterstrategietypen, um zu vermeiden, dass die Zusammenführung einen neuen Sequenzwert erzeugt, aber ich vermute, dass das problematisch wäre.
Tags und Links java hibernate persistence