-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 
Author Message
 Post subject: Unidirektionale Mappings mit Generated IDs und Cascading=ALL
PostPosted: Sun Jun 12, 2005 7:52 am 
Newbie

Joined: Wed Sep 08, 2004 9:19 am
Posts: 4
Ich habe zwei einfache Klassen A und B, die sich gegenseitig referenzieren. Dabei handelt es sich nicht um ein bidirektionales Mapping, sondern um zwei unabhängige unidirektionale Mappings. D.h. Jedes dieser Mappings kann gesetzt sein, oder auch nicht.

Bei beiden Mappings ist cascade="all" gesetzt, damit evtl. referenzierte Objekte mit persistiert werden.

Wenn ich jetzt neue zwei Instanzen erzeuge und verlinke und dann z.B. die Instanz von A persistiere, passiert fasst das erwartete, aber es gibt ein Problem.

ClassA classA = new ClassA();
ClassB classB = new ClassB();
classA.setClassB(classB);
classB.setClassA(classA);
session.save(classA);

Hibernate erkennt, dass classA und classB neue noch nicht persistierte Objekte sind. Da cascading eingeschaltet ist, wird erstmal classB persistiert . Dabei wird eine ID für die classB Instanz generiert (landet in ID in Tab. CLASS_B) und landet schliesslich auch als Foreign Key in der CLASS_B_ID Spalte in Tabelle CLASS_A.

Zum Abschluss der Transaktion wird classA persistiert. Wiederum wird eine ID generiert und auch korrekt als ID in CLASS_A gespeichert.

Jetzt das Problem:

Die Spalte CLASS_A_ID in Tabelle CLASS_B bleibt auf NULL.

Mir ist schon klar, dass zum Zeitpunkt als die classB Instanz persistiert wird, die ID von classA noch nicht generiert wurde, aber eigentlich hätte ich erwartet, dass der Cascading Mechanismus dies erkennt und für die fehlenden IDs ein UPDATE hinterherschickt.

Erwarte ich da zuviel oder mache ich irgendetwas falsch?

Das ganze ist ein vereinfachtes Beispiel aus einem reallen Modell, dass Instanzen von drei Klassen erzeugt, diese über mehrere Referenzen hin und her verknüpft und dann schliesslich persistiert. Leider fehlen an einigen Stellen dann die passenden Foreign Keys...


Hibernate version: 2.1.8
Mapping documents:

<class name="ClassA" table="CLASS_A">
<id name="id" column="ID" type="int">
<generator class="native"/>
</id>
<version column="VERSION" name="version" type="int" unsaved-value="null"/>

<many-to-one name="classB" column="CLASS_B_ID" class="ClassB" cascade="all"/>
</class>

Analog dazu Class B:

<class name="ClassB" table="CLASS_B">
<id name="id" column="ID" type="int">
<generator class="native"/>
</id>
<version column="VERSION" name="version" type="int" unsaved-value="null"/>

<many-to-one name="classA" column="CLASS_A_ID" class="ClassA" cascade="all"/>
</class>

Code between sessionFactory.openSession() and session.close():

ClassA classA = new ClassA();
ClassB classB = new ClassB();
classA.setClassB(classB);
classB.setClassA(classA);
session.save(classA);

Name and version of the database you are using: MySQL 4


Top
 Profile  
 
 Post subject: Re: Unidirektionale Mappings mit Generated IDs und Cascading
PostPosted: Fri Jun 17, 2005 7:12 am 
Newbie

Joined: Fri Jun 17, 2005 6:20 am
Posts: 10
Location: Hamburg, Germany
Hi Christian, hier treibst Du Dich also rum:


Man könnte nach der Instanzierung der Objekte diese gleich an die Session knüpfen. Dann die Felder setzen, dass automatic dirty checking würde gewährleisten, dass diese neue Info mit persistiert wird.

Etwa so:

ClassA classA = new ClassA();
session.save(classA);
ClassB classB = new ClassB();
session.save(classB);

classA.setClassB(classB);
classB.setClassA(classA);



Gruss, Ecki


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jun 17, 2005 8:11 am 
Newbie

Joined: Wed Sep 08, 2004 9:19 am
Posts: 4
Hi Ecki!

Das würde gehen, aber passt nicht so gut in die gewünschte Architektur.

Es gibt ja durchaus komplexe Objektgraphen, die durch den Benutzer in nicht definierter Reihenfolge erzeugt und verknüpft werden. Diese sollen dann am Ende der Bearbeitung persistiert werden.

Deine Lösung würde voraussetzen, den Objektgraphen erst bei Anbindung an die Session, also kurz vor dem Persistieren erneut aufzubauen. Ein solches Vorgehen führt den Service des Cascadierens irgendwie ad absurdum. Wenn ich sowieso wissen muss, welche Objekte mitzuspeichern sind, kann ich sie auch direkt per save() speichern.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jun 17, 2005 9:46 am 
Newbie

Joined: Fri Jun 17, 2005 6:20 am
Posts: 10
Location: Hamburg, Germany
Hi Christian,

ich sehe Dein Problem, Du wanderst beim Cascade="all" zunächst den Graph nach oben.

Grundsätzlich wird deshalb ja auch empfohlen, für ein <many-to-one> mapping das cascading auf "none" zu setzen, aber das hilft ja nicht weiter.

Vielleicht schaust Du Dir mal das Interceptor-Interface an, da gibts so Methoden wie onSave() oder onDelete(). Die scheinen ähnlich wie Oracle-BEFORE-Trigger zu funktionieren, ihr Einsatz wird gerade für Cascading saves bzw. deletes von abhängigen Objekten empfohlen.

Ecki


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.