2009-04-29 10 views
1

Ich habe eine viele-zu-eins-Beziehung zwischen den Objekten Product und Supplier. Ich muss in der Lage sein, Supplier zu löschen, ohne die Product s zu löschen, die zu ihm gehören.NHibernate viele-zu-eins-Beziehung löschen nur übergeordnete

Hier ist eine vereinfachte Version von Klassen ist:

public class Supplier { 
    public virtual IList<Product> Products { get; protected set; } 
} 

public class Product { 
    // Product belongs to a Category but Supplier is optional 
    public virtual Supplier Supplier { get; set; } 
    public virtual Category Category { get; set; } 
} 

ich FluentNHibernate bin mit, aber hier sind die Zuordnungen es produziert:

<bag name="Products" cascade="save-update" inverse="true"> 
     <key column="SupplierID" /> 
     <one-to-many class="Me.Product, Me, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> 
</bag> 

<many-to-one name="Supplier" column="SupplierID" /> 

einen Fremdschlüssel auf die Tabelle Artikel Dies schafft, Wenn ich also versuche, einen Lieferanten direkt zu löschen, erhalte ich einen Fremdschlüssel-Constraint-Fehler. Ich habe versucht, die Kaskade auf "alle" zu ändern, in der Hoffnung, dass dadurch möglicherweise nur die Beziehung gelöscht wird, aber alle Produkte und ihre anderen zugehörigen Objekte gelöscht wurden.

Der einzige Weg, den ich sehen kann, um dies jetzt zu lösen, besteht darin, die Sammlung Produkte des Lieferanten zu iterieren und die Eigenschaft Lieferant auf null zu setzen. Gibt es eine Möglichkeit, dieses Verhalten durch das Mapping zu erreichen?

+0

Der DB wird automatisch generiert, also nein. – roryf

+0

Außerdem hätte ich Phantom SupplierID Werte ohne Beziehung – roryf

Antwort

2

Die Zuordnungseigenschaften werden nur wirksam, wenn die Entität tatsächlich geladen wird und wenn Sie nicht über HQL abfragen. Wenn Sie beispielsweise Cascade=ALL angeben und Sie einen Lieferanten mit der Abfrage "delete from Supplier where id=:id" löschen, erhalten Sie wahrscheinlich den gleichen FK-Constraint-Fehler, weil der hql keine (programmatischen) Kaskaden auslöst.

Es scheint, dass die Produkte die besitzende Seite der Beziehung sind, die gut ist. Ich glaube, Sie haben zwei Möglichkeiten:

  • -Code einige Verfahren auf den Lieferanten über alle Produkte iterieren und setzen des Lieferanten Produkt auf null, und diese Methode verwenden, bevor Sie Lieferanten
  • vor dem Löschen ein Lieferant löschen Ausgabe machen sicher, dass Ihre DAO setzt den Lieferanten Produkt

Beispiel auf null:

public int Delete(Supplier s) { 
    return Session.CreateQuery("udpate Product set Supplier = null where Supplier = :supplier") 
     .SetParameter("supplier", s) 
     .ExecuteUpdate(); 
} 
+0

Hätte nicht gedacht, es als eine Abfrage innerhalb der Datenzugriffsebene zu tun, das war perfekt! – roryf

+0

Es stellt sich heraus, dass Sie UPDATE- oder DELETE-Anweisungen in HQL nicht ausführen können, dies ist nur in Raw SQL möglich. In diesem Fall kann ich damit leben. – roryf

+0

Sind Sie sicher? Ich benutze löschen überall in meinem Code: svc.getEm(). createQuery ("aus UserOperatorEJB löschen") .executeUpdate(); Überprüfen Sie auch diese Links: http://www.java2s.com/Code/Java/Hibernate/HQLDeleteHQL.htm http://twasink.net/blog/2005/04/differences-in-behaviour-between- hibernate-delete-queries-and-the-old-way/ Schade, dass die Hibernate-Docs-Site nicht verfügbar ist. –

0

dies nicht tun.

Sie haben eine implizite oder explizite Behauptung in Ihrem Modell, dass alle Produkte einen Lieferanten haben. Der Fremdschlüssel soll diese Bedingung durchsetzen. Wenn Sie den Anbieter entfernen, während Sie die Produkte behalten, verstößt er gegen Ihr Modell und wird wahrscheinlich dazu führen, dass ein Großteil Ihres Codes, der darauf beruht, dass dies immer der Fall ist, fehlschlägt.

Die eine Sache, die Sie tun können, haben Sie bereits entdeckt: Für jedes Produkt, das diesen Lieferanten hat, können Sie den Lieferanten des Produkts auf null setzen. Dies verletzt nicht Ihre Bedingung, aber es ist dasselbe wie zu sagen "wir wissen nicht, wer der Lieferant dieses Produkts ist" und kann Code-Fehler verursachen.

Warum möchten Sie das tun?

+0

Die Eigenschaft "Lieferant" des Produkts ist optional. Das Produkt gehört einem anderen Objekt als dem Lieferanten. Was würdest du vorschlagen? Eine Join-Klasse? – roryf

Verwandte Themen