2009-11-11 6 views
18

Ho due classi A e B. Molte B possono avere un'associazione con una singola A, quindi una relazione molti-a-uno da B a A . ho mappato il rapporto come:come definire un'eliminazione a cascata inversa su un mapping many-to-one in sospensione

<class name="A" table="tbl_A"> 
    <property name="propA" column="colA"/> 
</class> 
<class name="B" table="tbl_B"> 
    <property name="propB" column="colB"/> 
    <many-to-one name="a" class="A" column="col1" cascade="delete"/> 
</class> 

a non ha nulla mappato a B. Tenendo questo in mente abbiamo intenzione di eliminare B quando è associata a è cancellato. Questo sarebbe stato possibile se potessi definire un inverso = "true" sull'associazione many-to-one in B ma hibernate non lo consente.

Qualcuno può aiutare con questo? Non vogliamo scrivere nulla in A per questo.

+0

L'ho provato io stesso, non credo sia possibile. Potrebbe trattarsi di un bug in ibernazione, o l'ibernazione potrebbe pensare che ci sia una relazione uno-a-molti dall'altra parte, e decidere che l'eliminazione di un membro di una raccolta non dovrebbe comportare l'eliminazione dell'oggetto principale e di tutti i oggetti in quella collezione pure. – Zoidberg

+0

Puoi confermare che quello che vuoi fare è eliminare A e tutte le B associate ad A? –

+0

@Pascal si, è mia intenzione –

risposta

24

Iberna solo in cascata lungo le associazioni definite. Se A non sa nulla di Bs, nulla che fai con A influenzerà Bs.

suggerimento di Pascal è, quindi, il modo più semplice per fare quello che vuoi:

<class name="A" table="tbl_A"> 
    ... 
    <set name="myBs" inverse="true" cascade="all,delete-orphan"> 
    <key column="col1"/> 
    <one-to-many class="B"/> 
    </set> 
</class> 

<class name="B" table="tbl_B"> 
    ... 
    <many-to-one name="a" class="A" column="col1" not-null="true"/> 
</class> 

Nota che l'impostazione cascade="delete" su B come lo avete nel vostro codice originale non farà quello che vuoi - racconta Hibernate a "cancella A se B è cancellato", che rischia di provocare una violazione del vincolo (se ci sono altri Bs collegati a quella A).

Se non si riesce ad aggiungere una raccolta di Bs a A (anche se non posso davvero pensare alle circostanze in cui ciò si verificherà), l'unica altra alternativa è definire la cancellazione a cascata da A a B al livello di chiave estera; i tuoi Bs saranno cancellati quando la tua A viene cancellata.

Si tratta di una soluzione piuttosto brutto, però, perché bisogna essere estremamente attenti a come si elimina una in Hibernate:

  1. sessione deve essere lavata prima l'eliminazione di un aggiornamento (avendo sospeso a B può provocare in un errore o A e alcuni B vengono reinseriti dietro le quinte)
  2. Tutti i Bs collegati al tuo A (e poiché non stai mantenendo il rapporto da un lato che significa tutti Bs) devono essere sfrattati da tutti sessioni attive e cache di secondo livello.
+2

Bene, anche +1 per questa risposta completa e chiara. Ho davvero bisogno di migliorare il modo in cui spiegherò le cose su Hibernate in inglese :) –

+1

@Pascal - grazie. Penso che il tuo inglese sia perfetto, BTW. Inoltre, non è nemmeno la mia prima lingua, quindi cosa ne so? :-) – ChssPly76

+0

Non desidero mappare le raccolte ma ibernare mi costringe a farlo poiché è necessario il collegamento a cascata. Creato un problema: https://hibernate.atlassian.net/browse/HHH-8403 – djmj

7

Penso che sia necessario cascade="all,delete-orphan" da A a B con un'associazione one-to-many.

+0

+1. Non è quello che l'OP sta chiedendo, ma è il (solo) il modo giusto per farlo. – ChssPly76