2009-08-20 11 views
25

Sto riscontrando che i record orfani non vengono eliminati quando si rimuove da una raccolta in Sospensione. Io devo fare qualcosa di semplice sbagliato, (questo è Hibernate-101!), Ma non riesco a trovarlo ..Sospensione dell'eliminazione degli orfani durante l'aggiornamento della raccolta

Dato il seguente:

public class Book { 
    @ManyToOne 
    @NotNull 
    Author author; 
} 
public class Author 
{ 
    @OneToMany(cascade={CascadeType.ALL}) 
    List<Book> books; 
} 

E il codice seguente aggiornamento:

Author author = authorDAO.get(1); 
Book book = author.getBooks().get(0); 
author.getBooks().remove(0); 
authorDAO.update(author); 

AuthorDAO snippet:

@Override 
public void update(T entity) { 
    getSession().update(entity); 
} 

Di seguito la prova non riesce:

0.123.
Author author = author.get(1); 
assertEquals(0,author.getBooks().size()); // Passes 
Book dbBook = bookDAO.get(book.getId()) 
assertNull(dbBook); // Fail! dbBook still exists! 
assertFalse(author.getBooks().contains(dbBook) // Passes! 

In sintesi, mi sto trovando:

  • Mentre libro viene rimosso dalla collezione dell'autore di libri, esiste ancora nel database
  • Se esamino book.getAuthor().getBooks(), il libro non esiste in quella raccolta

Questo "sembra" come se non stessi svuotando la sessione o forzando un aggiornamento in modo appropriato - ma non sono sicuro di dove dovrei farlo. Lungo tale vena, altri punti che possono essere influire:

  • sto eseguendo quanto sopra in un test JUnit decorato con @RunWith(SpringJUnit4ClassRunner.class)
  • Originariamente ho colpito questo problema all'interno di una routine di aggiornamento che è decorato con @Transactional, tuttavia, Da allora l'ho ricreato in un semplice vecchio test di JUnit.

Qualsiasi consiglio sarebbe molto apprezzato!

MODIFICA: Grazie per tutto il feedback già. A seguito di commenti qui sotto, ho aggiunto il @Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN) al genitore, quindi è ora:

public class Author 
{ 
    @OneToMany(cascade={CascadeType.ALL}) 
    @Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN) 
    List<Book> books; 
} 

sto ancora trovando gli stessi risultati. DEVO mancare qualcosa di semplice.

risposta

16

Non stai facendo niente di male. Non stai semplicemente rimuovendo l'entità figlio. Puoi farlo con un remove() esplicito dell'entità figlio (oltre a quello che stai facendo) o usare quell'annotazione che causa la cancellazione dei record orfani.

Inoltre, vale la pena ricordare che lo CascadeType.DELETE non eliminerà neanche gli orfani. Ciò significa qualcos'altro. Vedi JPA CascadeType.ALL does not delete orphans.

Fondamentalmente per farlo automaticamente ti consigliamo questo sulla raccolta nel genitore:

org.hibernate.annotations.CascadeType.DELETE_ORPHAN 
+0

Ho aggiunto questa annotazione, ma non funziona ancora - gli stessi risultati di prima. –

+2

Stai anche impostando il riferimento dell'autore nel libro su null? – cletus

+0

No, pensavo che fosse il punto dell'annotazione DELETE_OPRHAN? –

0

provare a utilizzare il seguente annoation se si vuole 'transitiva delle dipendenze' behavour.

@ org.hibernate.annotations.Cascade (CascadeType.DELETE_ORPHAN)

3

L'opzione in cascata nel @OneToMany annotazione è un array, ciò che si vuole è:

@OneToMany(cascade={CascadeType.ALL, CascadeType.DELETE_ORPHAN}) 
0

si prega di aggiungere @onDelete forse questo lavoro per voi

public class Author 
{ 
    @OneToMany(cascade={CascadeType.ALL}) 
    @OnDelete(action = OnDeleteAction.CASCADE) 
    @Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN) 
    List<Book> books; 
} 
+0

Ciao. Anche questo non ha alcun effetto. –

+0

commetti la tua sessione o la svuota dopo l'eliminazione? – Am1rr3zA

0

Sembra che tu sia potrebbe mancare l'annotazione mappedBy. Prova:

public class Book { 
    @ManyToOne 
    @NotNull 
    Author author; 
} 
public class Author { 
    @OneToMany(mappedBy="author", cascade={CascadeType.ALL}) 
    List<Book> books; 
} 
35

per le persone che cercano la loro soluzione: Ora in Hibernate, resp. JPA 2.0, questo è il modo giusto:

@OneToMany(orphanRemoval=true) 
Problemi correlati