現在、Spring Dataリポジトリを使用して一部のエンティティを削除しようとしています。削除呼び出しは例外/エラーメッセージなしで機能しますが、エンティティはその後削除されません。
それらは私のエンティティです:
public class Board implements Serializable {
@Id
@GeneratedValue(generator = "uuid2")
@GenericGenerator(name = "uuid2", strategy = "uuid2")
@Column(columnDefinition = "BINARY(16)")
private UUID uuid;
@OneToMany(fetch=FetchType.EAGER, cascade=CascadeType.ALL, orphanRemoval = true, mappedBy = "board")
private List<Post> posts = new ArrayList<Post>();
}
そして
public class Post implements Serializable {
@Id
@GeneratedValue
private long id;
@ManyToOne(optional = false)
@JoinColumn(name="board_uuid", updatable = false, nullable = false)
@JsonBackReference
private Board board;
}
リポジトリは可能な限りシンプルです。
@Repository
public interface PostRepository extends CrudRepository<Post, Long> {
}
削除呼び出しは次のようなものです
postRepository.delete(50);
この変更がデータベースに反映されない理由はありますか?
編集1:
回避策を見つけましたが、実際の問題が何であるかまだわかりません。このように投稿を削除すると「機能」します(制約違反のためにいくつかの例外がありますが、それでも投稿は削除されます)。
post.setBoard(null);
postRepo.delete(post);
編集2:
実行されたSQLステートメントを見ると、休止状態が削除しようとしてさえいないことがわかります。発生する唯一のことは、これら2つのselectステートメントです。
Hibernate: select post0_.id as id1_1_0_, post0_.board_uuid as board_uu6_1_0_, post0_.content as content2_1_0_, post0_.x as x3_1_0_, post0_.y as y4_1_0_, post0_.z as z5_1_0_, board1_.uuid as uuid1_0_1_ from Post post0_ left outer join Board board1_ on post0_.board_uuid=board1_.uuid where post0_.id=?
Hibernate: select posts0_.board_uuid as board_uu6_0_0_, posts0_.id as id1_1_0_, posts0_.id as id1_1_1_, posts0_.board_uuid as board_uu6_1_1_, posts0_.content as content2_1_1_, posts0_.x as x3_1_1_, posts0_.y as y4_1_1_, posts0_.z as z5_1_1_ from Post posts0_ where posts0_.board_uuid=?
編集
投稿のcascade = CascadeType.ALLが問題のようです。それなしでは削除はうまく機能します(しかし、今では投稿への変更のカスケードが欠落しています)
問題は、cascade=CascadeType.ALL
を含むCascadeType.PERSIST
を使用しているようです。 CascadeType.PERSIST
は、子エンティティが親によって完全に管理され、直接削除できないことを意味します。削除するには、親から削除するだけです。
すべてではなく、他のCascadeTypes
を追加できます。例:CascadeType.REMOVE
(親が削除された場合に子を削除することだけが必要な場合).
上記のuser2936091からの優れた回答に基づいて、今日つまずいた(関連する)回避策について言及したかっただけです。親エンティティがHibernateコンテキストにフェッチされない場合、直接削除できます。
私の場合、これはfetch = FetchType.LAZY
上の@ManyToOne
関係。とにかくパフォーマンス上の理由でこの変更が必要でしたが、親が熱心にフェッチせずにHibernateがリポジトリメソッド呼び出しを介して自由に削除できることに気付きました。
cascade = CascadeType.PERSISTは、両側の挿入の更新に使用されますが、削除には制限されます。
@ManyToOne(cascade=CascadeType.PERSIST, fetch = FetchType.LAZY)
// @JoinColumn(name = "qid")
@JoinColumn(name = "qid", referencedColumnName = "qid", foreignKey = @ForeignKey(name = "qid"), nullable = false)
// @JsonIgnore
@JsonBackReference
private QueueGroup queueGroup;
これは、PostクラスにmappedBy = "board"を設定して、PostのマスターがBoardであることを伝えるためです。
簡単な代替手段:
@Repository
public interface PostRepository extends CrudRepository<Post, Long> {
@Modifying(clearAutomatically = true, flushAutomatically = true)
@Query(value = "DELETE FROM post WHERE id = ?1", nativeQuery = true)
void deleteById(long postId);
}