I'm finding that orphan records aren't being deleted when removing from a collection in Hibernate. I must be doing something simple wrong, (this is Hibernate-101!), but I can't find it..
Given the following:
public class Book {
@ManyToOne
@NotNull
Author author;
}
public class Author
{
@OneToMany(cascade={CascadeType.ALL})
List<Book> books;
}
And the following update code:
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);
}
The following test the fails:
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 summary, I'm finding:
book.getAuthor().getBooks()
, book does not exist in that collectionThis "feels" like I'm not flushing the session or forcing an update appropriately - but I'm not sure where I should be doing that. Along that vein, other points that may be impacting:
@RunWith(SpringJUnit4ClassRunner.class)
@Transactional
, however, I have since recreated it in a plain old JUnit test.Any advice would be greatly appreciated!
EDIT: Thanks for all the feedback already. Further to comments below, I've added the @Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
to the parent, so it's now:
public class Author
{
@OneToMany(cascade={CascadeType.ALL})
@Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
List<Book> books;
}
I'm still finding the same results. I MUST be missing something simple.
for people searching for their solution: Now in Hibernate, resp. JPA 2.0, this is the right way:
@OneToMany(orphanRemoval=true)
You're not doing anything wrong. You're just not removing the child entity. You can either do this with an explicit remove() of the child entity (in addition to what you're doing) or use that annotation that causes orphan records to be deleted.
Also, it's worth mentioning that CascadeType.DELETE
won't delete orphans either. That means something else. See JPA CascadeType.ALL does not delete orphans.
Basically to do this automatically you'll want this on the collection in the parent:
org.hibernate.annotations.CascadeType.DELETE_ORPHAN
The cascade option in the @OneToMany
annotation is a array, what you want is:
@OneToMany(cascade={CascadeType.ALL, CascadeType.DELETE_ORPHAN})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With