Hibernate在更新集合时删除孤立

我发现从Hibernate中的集合中删除时不会删除孤立记录。 我必须做一些简单的错误,(这是Hibernate-101!),但我找不到它..

鉴于以下内容:

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

以下更新代码:

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

AuthorDAO代码段:

 @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() ,那个集合中不存在book

这种“感觉”就像我没有冲洗会话或强制更新 – 但我不确定我应该在哪里做。 沿着这条路线,可能影响的其他点:

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

任何建议将不胜感激!

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

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

我仍然找到相同的结果。 我必须遗漏一些简单的东西。

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

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

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

 org.hibernate.annotations.CascadeType.DELETE_ORPHAN 

对于寻找解决方案的人:现在在Hibernate,resp。 JPA 2.0,这是正确的方法:

 @OneToMany(orphanRemoval=true) 

@OneToMany注释中的级联选项是一个数组,您想要的是:

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

如果您想要“传递依赖”行为,请尝试使用以下内容。

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

请添加@onDelete也许这项工作适合你

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

看起来你可能会错过mappedBy注释。 尝试:

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