2015-02-25 4 views
12

Ich habe die folgende Anordnung der Klassen:Reihenfolge der kaskadierten GORM-Speicherung abhängig von Feldnamen? "Ja wirklich?"

class A { 
    static belongsTo = [c: C] 
    B b 
} 

class B { 
    static belongsTo = [c: C] 
} 


class C { 
    static hasMany = [bbs: B, aas: A] 
} 

Wenn ich jetzt Instanzen dieser Klassen erstellen ...

B b = new B() 
A a = new A() 
a.b = b 

C c = new C() 
c.addToBbs(b) 
c.addToAas(a) 

... und versuchen, c zu retten ...

c.save() 

... Ich bekomme eine org.hibernate.TransientObjectException Message object references an unsaved transient instance - save the transient instance before flushing: B.

Was ich denke GORM ist zuerst zu kaskadieren das Speichern auf c.aas und dann stolpert über die Instanz a.b, die noch nicht gespeichert ist. Daher die Ausnahme.

Jetzt der Trick: Wenn ich die aas Eigenschaft C-xxs umbenannt, es funktioniert:

class C { 
    static hasMany = [bbs: B, xxs: A] 
} 

b zuerst, dann a gespeichert wird. GORM scheint die Saves in lexikographischer Reihenfolge der Felder zu kaskadieren (zuerst bbs, dann xxs)!

Wie kann ich die Sequenz steuern, die GORM für die kaskadierende Speicherung verwendet (außer das Umbenennen der Felder, was mir sehr spröde erscheint)?

+1

Dies könnte nicht Ihre genaue Frage beantworten, wurden aber speichert die in einer Transaktion eingewickelt? Ich würde deinen ersten Versuch erwarten zu arbeiten, solange alles transaktional ist. –

+0

Ja. Beim Speichern gab es eine aktive Transaktion. –

+0

Entschuldigung, klicken Sie zu früh auf den Bearbeitungsschaltfläche. Funktioniert es, wenn Sie "c.addToAas (a)" (ohne das c.addToBbs (b)) verwenden? Ich bin mir nicht sicher, ob die Partien auf ein drittes Level fallen werden, aber es lohnt sich. Ich würde auch gerne wissen, ob Gauravs Vorschlag für "cascade: save" funktioniert, aber ich würde nicht erwarten, dass es einen Unterschied macht. Angesichts der Standard-Mapping für hasMany ist "cascade: all".) –

Antwort

0

Soweit ich weiß, bietet GORM keine Möglichkeit, die Reihenfolge zu steuern, in der Speicherkaskaden auf Eigenschaften angewendet werden.

Ich denke, Sie sollten diese in der Lage sein, zu lösen, indem Sie eine der folgenden Ansätze:

1] Explizit B ‚s Instanz vor A Speichern‘ speichern s (wie man immer tut für einen einzigen Verein ohne belongsTo

)
B b = new B().save() 
A a = new A(b: b) // b should already be persisted as A doesn't `belongsTo` B 
C c = new C() 
c.addToBbs(b) 
c.addToAas(a) 
c.save() 

2] definieren custom cascading behavior für Immobilien b in Klasse A

class A { 
    static belongsTo = [c: C] 
    B b 

    static mapping = { 
     b cascade: 'save' 
    } 
} 

Hinweis: weder Ansatz getestet wurde

0

In meinem many-to-many ist, speichere ich Klasse C, bevor ich versuche .addTo des

B b = new B() 
A a = new A() 
a.b = b 

C c = new C() 
c.save() 
c.addToBbs(b) 
c.addToAas(a) 

Und ich muss Gewohnheit haben zu tun definieren Verhalten Kaskadierung unter bestimmten Umständen.

Diese Artikel helfen, Probleme wie diese zu verstehen.

https://spring.io/blog/2010/06/23/gorm-gotchas-part-1/

https://spring.io/blog/2010/07/02/gorm-gotchas-part-2/

https://spring.io/blog/2010/07/28/gorm-gotchas-part-3/

+0

Das funktioniert nicht für mich. C kann nicht ohne die A's und B's gespeichert werden. Ich kenne die GORM-Artikel (du hast Recht, sie sind wirklich gut). –

+0

Ja, die Reihenfolge, in der gespeichert wird, ist wichtig, und was beim Speichern in Kaskade geht. Anstatt aas zu xxs zu ändern, um es in der alphabetischen Reihenfolge zu speichern, ist die bessere Lösung herauszufinden, was zuerst gespeichert werden muss, und sie in dieser Reihenfolge zu speichern ... Es ist nicht sehr benutzerfreundlich, oder? –

Verwandte Themen