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

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

「推移的な依存関係」の動作が必要な場合は、次の注釈を使用してみてください。

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

于 2009-08-20T08:52:43.057 に答える
0

please add @onDelete maybe this work for you

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 に答える