2008-10-13 14 views
9

Ich habe eine Entität [Projekt], die eine Sammlung anderer Entitäten enthält [Fragen].Hibernate Delete Cascade

Ich habe die Beziehung mit einem Kaskadenattribut von "all-delete-orphan" gemappt.

In meinem DB ist die Beziehung mit einem Feld project_id (FK) in der Fragetabelle zugeordnet. Dieses Feld kann nicht null sein, da ich keine Frage ohne ein Projekt haben möchte.

Wenn ich session.delete (Projekt) mache, löst es eine Ausnahme aus, die besagt, dass project_id nicht null sein kann, aber wenn ich die Nicht-Null-Einschränkung in dieses Feld entferne, funktioniert die Löschung gut.

Wer weiß, wie man das löst?

+0

Sie sollten wahrscheinlich die relevanten Teile Ihrer Abbildungen zeigen. Ich verwende all-delete-orphan die ganze Zeit mit Nicht-Null-Fremdschlüsseln und hatte noch nie ein Problem. –

Antwort

-2

Das Löschen findet zuerst im Projekt statt und wird in die Frage kaskadiert, aber das Projekt delete enthält ein Nullen der project_id in den Fragen (für referenzielle Integrität. Sie erhalten keine Ausnahme beim Löschen des Frageobjekts , sondern weil die Kaskade versucht, die FK in der Frage (n) auf null.

mit Blick auf „Java Persistence with Hibernate“, denke ich, dass das, was Sie wirklich eine Kaskade Typ löschen oder entfernen möchten, nicht löschen-Waisen.

+0

Das löst nichts –

0

Eine Strategie besteht darin, den Fremdschlüssel mit on-delete-cascade in der Datenbank zu markieren. Sobald NHibernate der Datenbank mitteilt, ein Projekt zu löschen, kaskadiert die Datenbank selbst die löscht. Dann müssen Sie NHibernate mitteilen, dass die Datenbank selbst eine Kaskadenlöschung durchführt.

+0

ist das möglich mit Nhibernate 1.2? –

11

Direkt von der documentation. Dies erklärt das Problem genau ich glaube:

jedoch dieser Code

Parent p = (Parent) session.Load(typeof(Parent), pid); 
// Get one child out of the set 
IEnumerator childEnumerator = p.Children.GetEnumerator(); 
childEnumerator.MoveNext(); 
Child c = (Child) childEnumerator.Current; 

p.Children.Remove(c); 
c.Parent = null; 
session.Flush(); 

nicht c aus der Datenbank entfernen; Es wird nur den Link zu p entfernen (und in diesem Fall eine NOT NULL-Constraint-Verletzung verursachen). Sie müssen das Kind explizit löschen().

Parent p = (Parent) session.Load(typeof(Parent), pid); 
// Get one child out of the set 
IEnumerator childEnumerator = p.Children.GetEnumerator(); 
childEnumerator.MoveNext(); 
Child c = (Child) childEnumerator.Current; 

p.Children.Remove(c); 
session.Delete(c); 
session.Flush(); 

Nun, in unserem Fall kann ein Kind ohne seine Eltern nicht wirklich existieren. Wenn wir also ein Kind aus der Sammlung entfernen, wollen wir es wirklich löschen. Dazu müssen wir cascade = "all-delete-orphan" verwenden.

<set name="Children" inverse="true" cascade="all-delete-orphan"> 
    <key column="parent_id"/> 
    <one-to-many class="Child"/> 
</set> 

Edit:

In Bezug auf das inverse material, ich glaube, das ist bestimmt nur, wie die SQL erzeugt wird, sieht diese doc für weitere Informationen.

Eines ist zu beachten, haben Sie

bekam
not-null="true" 

auf der Viele-zu-Eins-Beziehung in Ihrem Hibernate Config?

+0

Entschuldigung. Das funktioniert, aber ich verstehe nicht warum. Aus den Dokumenten geht hervor, dass inverse true verwendet wird, wenn Sie eine bidirektionale Assoziation zuordnen (und das ist nicht mein Fall), das Hinzufügen macht es trotzdem gut. Vielen Dank.Wenn du erklärst, warum inverse = true funktioniert, akzeptiere ich deine Antwort –

+0

Gibt es ein Beispiel dafür aus den Hibernate-Dokumenten? Es scheint mir komisch, dass er nach dem Winterschlaf gefragt hat und Sie mit einer gewissen Dokumentation beantwortet haben. – kbaribeau

+0

Ich habe einige zusätzliche Informationen für Sie hinzugefügt. Froh, dass das für Sie funktioniert hat :) – abarax

Verwandte Themen