2009-08-20 14 views
25

Zauważam, że rekordy osierocone nie są usuwane podczas usuwania z kolekcji w stanie hibernacji. Muszę robić coś prostego źle, (jest to Hibernate-101!), Ale nie mogę go znaleźć ..Hibernowanie usuwa sieroty podczas aktualizacji kolekcji

Biorąc pod uwagę następujące elementy:

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

i następujący kod aktualizacji:

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); 
} 

Poniższy Test nie powiedzie:

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! 

Podsumowując, jestem znalezienia:

  • Choć książka jest usuwany z kolekcji Autora książek, to nadal istnieje w bazie danych
  • Gdybym zbadać book.getAuthor().getBooks(), książka nie istnieje w ta kolekcja:

"Czuję się" tak, jakbym nie spłukiwał sesji lub nie zmusił do aktualizacji - ale nie jestem pewien, gdzie powinienem to zrobić. Wzdłuż tej żyły, inne punkty, które mogą być wpływając:

  • mam wykonywania powyższych czynności w teście JUnit ozdobione @RunWith(SpringJUnit4ClassRunner.class)
  • pierwotnie hit tego problemu wewnątrz procedury aktualizacji, który jest ozdobiony @Transactional jednak, Odtąd odtworzyłem go w zwykłym starym teście JUnit.

Każda rada byłaby bardzo ceniona!

EDYCJA: Dzięki za wszystkie opinie już. Dalsze komentarze poniżej, Dodałem @Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN) do rodzica, dlatego teraz:

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

ja wciąż znalezienie takich samych wyników. Muszę przegapić coś prostego.

Odpowiedz

16

Nie robisz niczego złego. Po prostu nie usuwasz elementu podrzędnego. Możesz to zrobić za pomocą jawnego remove() elementu podrzędnego (oprócz tego, co robisz) lub użyj tej adnotacji, która powoduje usunięcie rekordów osieroconych.

Warto również wspomnieć, że CascadeType.DELETE również nie usunie sierot. To oznacza coś innego. Zobacz JPA CascadeType.ALL does not delete orphans.

Zasadniczo to zrobić automatycznie będziesz chciał to na gromadzeniu w dominującej:

org.hibernate.annotations.CascadeType.DELETE_ORPHAN 
+0

Dodałem tę adnotację, ale nadal nie działa - takie same wyniki jak wcześniej. –

+2

Czy ustawiasz również odniesienie do autora w książce na wartość null? – cletus

+0

Nie, pomyślałem, że to była przyczyna adnotacji DELETE_OPRHAN? –

0

spróbować wykorzystać poniższe annoation jeśli chcesz „” behavour przechodni zależnościach.

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

3

Opcja kaskada w @OneToMany adnotacji jest tablicą, co chcesz, to:

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

proszę dodać @onDelete może ta praca dla ciebie

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

Witam. To również nie ma wpływu. –

+0

czy zatwierdzasz sesję, czy opróżniasz ją po usunięciu? – Am1rr3zA

0

Wygląda na to, że jesteś może brakować adnotacji mappedBy. Wypróbuj:

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

dla osób poszukujących rozwiązania: teraz w trybie hibernacji, wzgl. JPA 2.0, to jest właściwa droga:

@OneToMany(orphanRemoval=true) 
Powiązane problemy