2014-10-13 25 views
5

Sto tentando con molta fatica di eliminare un'entità coinvolta in varie relazioni (solo @ManyToOne). Tuttavia, Hibernate non elimina nulla, dopo aver chiamato em.remove, tutto rimane invariato.Hibernate EntityManager: rimozione entità di riferimento non funzionante


Ho 5 entità (E1 - E5), fa riferimento l'entità (E6) in questione in questo modo:

@Entity 
public class EX { 
    @OneToMany(mappedBy = "eX", fetch = FetchType.EAGER, cascade = { CascadeType.PERSIST, CascadeType.REMOVE }) 
    private Set<E6> e6s; 
} 

E6 sé ha il rovescio @ManyToOne Relazioni:

public class E6{ 

    @ManyToOne(optional = false) 
    private E1 e1;  

    @ManyToOne(optional = false) 
    private E2 e2; 

    @ManyToOne(optional = false) 
    private E3 e3; 

    @ManyToOne(optional = false) 
    private E4 e4; 

    @ManyToOne(optional = false) 
    private E5 e5; 
} 

(a sinistra out id, colonne aggiuntive ecc ...)


Ogni volta che chiamo em.remove(instanceOfE6), semplicemente non succede nulla. Ho aggiunto Hibernate SQL-Output e non riesco a vedere un singolo tentativo di eseguire una query DELETE.

Dal momento che la cancellazione può avvenire da una richiesta AJAX e un fresco EntityManager, ho aggiunto una chiamata di fondere prima della cancellazione, causo otherwhise ottengo un Entity eccezione non gestita:

em.remove(em.merge(instanceOfE6)); 

Ma niente . Lo stato rimane invariato.

Così ho provato ad aggiungere un metodo @PreRemove per cancellare tutte le relazioni prima di rimuovere l'entità ... Il metodo non viene mai chiamato.

Ho provato varie operazioni in cascata (compreso Cascade.ALL), ma poiché tutto ciò di cui ho bisogno è rimuovere e persistere, anche questo dovrebbe funzionare.


ho pensato di usare un'istruzione DELETE nativo (ogni entità ha un id surrogata, in modo che molto probabilmente di lavoro) - ma dal momento che tutto avviene all'interno di un AJAX-chiamata, non voglio usare quel , perché voglio aggiornare Persistence-Cache senza ritirare tutte le entità coinvolte ...

Qualche idea?

Se hai bisogno di più fonti, lasciami un commento.


Ho anche provato a rimuovere l'ente in questione da tutti i rapporti (oggetto saggio), e chiamare em.merge() su una delle entità rimanenti, sperando che Hibernate whipe l'entità non collegato - senza fortuna.

+1

Hai commesso la transazione? –

+0

Hai chiamato 'em.flush()'? – jmvivo

+0

@DavidLevesque Esecuzione di Hibernate in modalità autocommit ... – dognose

risposta

13

ho capito il problema (s) - Actual ci sono stati due di loro: (Lasciando questo qui, se qualcuno si imbatte in un problema simile)

Come ho già detto, la cancellazione dovrebbe avere successo in un Ajax richiesta. Pertanto, chiamata semplice

em.remove(instanceOfE6); 

ha provocato un'eccezione java.lang.IllegalArgumentException: Removing a detached instance.Così, ho provato l'approccio con unione:

em.remove(em.merge(instanceOfE6)); 

che non producono un errore - ma semplice non ha funzionato. Ho permesso trace-registrazione per Hibernate come accennato in questo post: JPA/Hibernate remove entity sometimes not working di capire cosa è andato storto, e anzi, cercando di rimuovere l'entità stata:

TRACE [org...DefaultPersistEventListener] un-scheduling entity deletion ... 

Ovviamente l'entità di rimuovere è ancora collegato ad altre entità , che ha portato al problema che l'ibernazione ha interrotto la cancellazione, quindi ho provato a rimuovere le relazioni prima della cancellazione. Come si può vedere dall'esempio di E6, ho usato @ManyToOne(optional = false), il che significa che non posso impostare i riferimenti in uscita a null, o causerà eccezioni quando si chiama merge.

Il mio primo tentativo di pulire le relazioni era solo "pulire i set", perché ritenevo che non fosse necessario pulire le relazioni in uscita dell'entità che si desidera eliminare. Non è, ma io delineare in dettaglio un po 'più tardi:

Quindi, il codice ora sembrava

instanceOfE6.getE1().getE6s().remove(instanceOfE6); 
instanceOfE6.getE2().getE6s().remove(instanceOfE6); 
instanceOfE6.getE3().getE6s().remove(instanceOfE6); 
instanceOfE6.getE4().getE6s().remove(instanceOfE6); 
instanceOfE6.getE5().getE6s().remove(instanceOfE6); 

em.remove(em.merge(instanceOfE6)); 

Stesso problema: l'eliminazione interrotta. Ho perso il fatto ovvio, che chiamando merge sarà ofc. ripristinare le voci all'interno dei set che ho appena rimosso, perché instanceOfE6 STILL non ha riferimenti nullable sulle altre entità. Pertanto la cancellazione è stata interrotta nuovamente.

Infine la soluzione di c. era fare la l'unione prima di rimuovere i riferimenti e la cancellazione definitiva:

if (!em.contains(instanceOfE6)){ 
    instanceOfE6 = em.merge(instanceOfE6); 
} 

instanceOfE6.getE1().getE6s().remove(instanceOfE6); 
instanceOfE6.getE2().getE6s().remove(instanceOfE6); 
instanceOfE6.getE3().getE6s().remove(instanceOfE6); 
instanceOfE6.getE4().getE6s().remove(instanceOfE6); 
instanceOfE6.getE5().getE6s().remove(instanceOfE6); 

em.remove(instanceOfE6); 

Io non sono del tutto sicuro se ho spiegato tutto accurato al 100%, ma almeno posso riprodurre e risolvere il problema cambiando il codice avanti e indietro.

+2

Sei un vero toccasana. Sono stato alle prese con questo per due ore. Grazie mille. Gente, fai attenzione agli alberi delle entità (dovevo scrivere groupToRemove.getParent(). GetSubgroups(). Remove (groupToRemove), e dovevo mappare parent con cascade = CascadeType.MERGE). Cheers – jpangamarca

+1

'groupToRemove.getParent(). GetSubgroups(). Remove (groupToRemov e)' Questo è esattamente ciò che ho fatto. Sembra f **** strano ... ma entrarci: è logico :-) – dognose