Ändern des Typs einer Entität, die ihre ID bewahrt

8

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?

    
artemb 13.07.2009, 11:08
quelle

5 Antworten

11

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:

  1. Eviction B aus der Sitzung, wenn sie da ist (das ist wichtig)
  2. Führen Sie Ihre benannte Abfrage aus.
  3. Laden Sie, was-jetzt-bekannt-wie-C bekannt ist, indem Sie die ID des ehemaligen B verwenden.
  4. Aktualisieren / setzen Sie Attribute nach Bedarf.
  5. Persist C
ChssPly76 11.09.2009, 03:14
quelle
2

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.

    
skaffman 13.07.2009 11:26
quelle
0

Sie können Ihre eigene ID verwenden (nicht generiert) und folgendermaßen vorgehen:

  1. Retrive B
  2. offene Transaktion
  3. lösche B
  4. Übernehmen Sie die Transaktion
  5. öffne eine neue Transaktion
  6. erstelle C und behalte es bei
  7. Schließen Sie die zweite Transaktion

Auf diese Weise werden Sie die ID aus der Tabelle löschen, bevor Sie sie erneut als C einfügen.

    
David Rabinowitz 13.07.2009 11:31
quelle
0

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.

    
Damo 13.07.2009 11:54
quelle
0

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.

    
Petriborg 14.07.2009 19:56
quelle

Tags und Links