32

我发现从 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)
  • 我最初在一个用 装饰的更新例程中遇到了这个问题@Transactional,但是,我已经在一个普通的旧 JUnit 测试中重新创建了它。

任何建议将不胜感激!

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

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

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

4

7 回答 7

43

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

@OneToMany(orphanRemoval=true)
于 2012-12-12T00:08:48.893 回答
20

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

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

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

org.hibernate.annotations.CascadeType.DELETE_ORPHAN
于 2009-08-20T08:51:17.273 回答
3

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

@OneToMany(cascade={CascadeType.ALL, CascadeType.DELETE_ORPHAN})
于 2009-08-20T08:54:20.120 回答
0

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

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

于 2009-08-20T08:52:43.057 回答
0

请添加@onDelete 也许这对你有用

public class Author
{
    @OneToMany(cascade={CascadeType.ALL})
    @OnDelete(action = OnDeleteAction.CASCADE)
    @Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
    List<Book> books;
}
于 2009-08-20T10:13:34.580 回答
0

看起来您可能缺少mappedBy注释。尝试:

public class Book {
  @ManyToOne
  @NotNull
  Author author;
}
public class Author {
  @OneToMany(mappedBy="author", cascade={CascadeType.ALL})
  List<Book> books;
}
于 2009-08-21T04:29:55.740 回答
0

我知道我迟到了,我意识到关于这个话题已经说了很多,但恕我直言,我不会使用 delete-orphans 作为级联选项。我宁愿在删除父级之前手动删除子级关联。一个轻微的疏忽……一长串的关联可以在一秒钟内被删除。是的!我同意在某些情况下这可能正是人们想要的。

于 2019-07-01T18:11:27.390 回答