休眠在更新集合时删除孤立项

2022-09-01 09:29:38

我发现从Hibernate中的集合中删除时,孤立记录不会被删除。我一定是做错了什么(这是Hibernate-101!),但我找不到它。

给定以下内容:

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

以及以下更新代码:

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

作者DAO片段:

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

以下测试失败:

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!

总之,我发现:

  • 虽然书籍已从作者的书籍收藏中删除,但它仍存在于数据库中
  • 如果我检查,该馆藏中不存在这本书book.getAuthor().getBooks()

这“感觉”好像我没有刷新会话或适当地强制更新 - 但我不确定我应该在哪里这样做。沿着这条脉络,可能影响的其他要点:

  • 我正在执行上述操作,并在 JUnit 测试中装饰@RunWith(SpringJUnit4ClassRunner.class)
  • 我最初在一个带有 装饰的更新例程中遇到了这个问题,但是,我已经在一个普通的旧JUnit测试中重新创建了它。@Transactional

任何建议将不胜感激!

编辑:感谢所有的反馈。除了下面的评论,我已经将 添加到父级,所以它现在是:@Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)

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

我仍然发现相同的结果。我一定错过了一些简单的东西。


答案 1

对于寻找解决方案的人来说:现在在Hibernate中,或者JPA 2.0,这是正确的方法:

@OneToMany(orphanRemoval=true)

答案 2

你没有做错任何事。您只是没有删除子实体。您可以使用子实体的显式 remove() 来执行此操作(除了您正在执行的操作之外),也可以使用导致删除孤立记录的批注。

另外,值得一提的是,这也不会删除孤儿。这意味着别的东西。请参阅 JPA CascadeType.ALL 不会删除孤立项。CascadeType.DELETE

基本上,要自动执行此操作,您需要在父级的集合上执行此操作:

org.hibernate.annotations.CascadeType.DELETE_ORPHAN

推荐