2009-02-14 7 views
10

Si verificano problemi durante la rimozione di un elemento da un elenco. L'elenco è definito in una superclasse, ma le annotazioni Hibernate sono applicate agli accessor di proprietà in una sottoclasse. Ci sono due metodi nella superclasse che manipolano la lista. Il metodo "aggiungi" funziona bene, ma la "rimozione" non mantiene i cambiamenti. Ho controllato le mie impostazioni Cascade e mi sembra di avere le cose corrette. Sto facendo qualcosa che è impossibile. In caso contrario, sto facendo qualcosa in modo errato?Ibernazione: la rimozione di un elemento da un elenco non persiste

Qui sono i miei corsi:.

@Entity 
abstract class Temporal<T> { 
    @Id 
    @GeneratedValue 
    private Long id; 

    @Version 
    private Integer version = null; 

    @Transient 
    protected List<T> content = new ArrayList<T>(); 

    public void remove(T value) { 
     // business logic ... 
     content.remove(value); 
    } 

    public void add(T value) { 
     // business logic ... 
     content.add(value); 
    } 
} 

@Entity 
@AccessType("property") 
class TemporalAsset extends Temporal<Asset> { 
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "temporal") 
    public List<Asset> getContent() { 
     return super.content; 
    } 

    protected void setContent(List<Asset> list) { 
     super.content = list; 
    } 
} 

Io uso un'istanza della classe TemporalAsset come segue (nota che sto utilizzare solo il metodo di "refresh" per dimostrare il comportamento L'elenco non persistono correttamente anche se chiudo o chiudo la sessione e apro una nuova sessione):

temporalAsset.add(value1); 
temporalAsset.getContent().size() == 1; // true 
session.update(temporalAsset); 

session.refresh(temporalAsset); 

temporalAsset.getContent().size() == 1; // true 

temporalAsset.remove(value1); 
temporalAsset.getContent().size() == 0; // true 
session.update(temporalAsset); 

session.refresh(temporalAsset); 

temporalAsset.getContent().size() == 0; // false, its 1 

Grazie.

risposta

14

È necessario specificare in modo esplicito a cascata come CascadeType.DELETE_ORPHAN.

tenta di modificare il codice per

@OneToMany  
@Cascade(cascade = {CascadeType.ALL, CascadeType.DELETE_ORPHAN}, mappedBy = "temporal") 

Parte da hibernate docs:

Se la durata della vita dell'oggetto figlio è delimitata dalla durata di vita dell'oggetto padre , fare il genitore di un completo oggetto del ciclo di vita specificando CascadeType.ALL e org.hibernate.annotations.CascadeType.DELETE_ORPHAN (fare riferimento alla guida di riferimento Hibernate per la semantica di orfano eliminare)

+0

E 'stato! grazie mille – codefinger

+0

CascadeType.DELETE_ORPHAN è deprecato. C'è un'alternativa? –

+5

usa @OneToOne (orphanRemoval = true) o @OneToMany (orphanRemoval = true) secondo http://docs.jboss.org/hibernate/orm/3.5/api/org/hibernate/annotations/CascadeType.html – FoxyBOA

0

Provare a rimuovere le chiamate a Session.refresh(). Da documenti:

Rilanciare lo stato dell'istanza data dal database sottostante. È sconsigliabile utilizzarlo per implementare sessioni di lunga durata che coprono molte attività aziendali. Questo metodo è tuttavia utile in determinate circostanze speciali . Ad esempio

  • cui un trigger del database altera lo stato dell'oggetto su inserto o aggiornare
  • dopo l'esecuzione SQL diretta (ad es. Un aggiornamento di massa) nella stessa sessione
  • dopo aver inserito un blob o Clob

http://www.hibernate.org/hib_docs/v3/api/org/hibernate/Session.html#refresh(java.lang.Object)

Se si chiama flush() prima di refresh(), che potrebbe risolvere il problema, in quanto anche a filo () garantisce che qualsiasi SQL in sospeso verrà eseguito contro il DB. In pratica non ho quasi mai visto nessuno usare refresh() e non sembra dal tuo codice che ne hai bisogno.

Questo capitolo dalla documentazione è la pena di leggere:

http://www.hibernate.org/hib_docs/v3/reference/en/html/objectstate.html

+0

Ho incluso solo l'aggiornamento qui per dimostrare il comportamento. In pratica, lo svuotamento non mantiene le modifiche alla lista. Posso persino chiudere la sessione, aprire una nuova sessione e l'elenco ha ancora il valore in esso. – codefinger

0

Hai segnato il campo 'contenuto' come transitoria nella classe eccellente. Almeno sospetterei che ciò stia causando problemi. Con la mappatura nella sottoclasse, in pratica hai ora due mappature contraddittorie per lo stesso attributo.

+0

pensi , ma questo non causa problemi – codefinger

Problemi correlati