Java
jpa
spring-boot

OneToManyのリストフィールドの削除・更新の仕方

問題

  • reposytoryに主キーでdeleteメソッドを送っても、当該レコードが削除されないらしく、再表示用のhdr検索で、dtlが検索されてしまう

  • 以下のようなentityをもつ

  • dtlEntityは子データ(明細)

  • hdrEntityが親

- hdrEntityは、以下のようにリストフィールドにdtlEntityを持つ

HdrEntity
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "tMitsumoriHdrEntity")
    @JsonIgnore
    private List<DtlEntity> dtlEntity;
  • コントローラ上で、dtlEntityをリポジトリのdeleteメソッドで削除を行うが、画面上では消えたように見えるが、画面を別のリクエスト後に生き返る、永続化がうまくできていないらしい

前提

  • Spring-boot 3.7.1
  • Spring Tool Suite Version: 3.7.1.RELEASE
  • java

対策

1. 関連Entityの直接削除は行わない

  • 関連を持つ場合、直接削除するとhdrの方にデータが残ってしまい、削除が戻ってしまう
dtlRepository.delete(dtlEntity);
  • だけだると、HdrEntityの方にまだそのdtlEntityが残ってしまっていて、消えない

2. orphanRemovealをtrueにする

  • oneToManyに、orphanRemoval=true属性をつけないと、関連テーブルを削除してもメモリ上だけで、永続化がされない
// 明細テーブル
    @OneToMany(cascade = CascadeType.ALL, orphanRemoval=true, fetch = FetchType.EAGER, mappedBy = "tMitsumoriHdrEntity")
    @JsonIgnore
    private List<DtlEntity> dtlEntity;

3. A collection with cascade="all-delete-orphan" was no longer referencedエラーの対処

  • リストで関連entityをフィールドで持つとき、clearメソッドで関連づけをクリアしてaddして入れ直す、という方法で永続化を行わなければならない

  • NG例

HdrEntity.setDtlEntity(saveDtlList);
HdRepository.save(HdrEntity);

  • リストの項目数が変わる変更を行うとき、
  • 消したいEntityをremove後のリストをフィールドに代入し、

- リポジトリのsaveで永続化を行なった場合

A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance
  • エラーが発生する

  • 正しい

HdrEntity.getDtlEntity().clear();
HdrEntity.getDtlEntity().addAll(saveDtlList);
HdRepository.save(HdrEntity);

  • 先に、Entityのリストが入るフィールドをclear()し、
  • もう一度そのフィールドに変更後のリストを入れ直す

参考

HibernateException - A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance

http://cristian.sulea.net/blog.php?p=2014-06-28-hibernate-exception-a-collection-with-cascade-all-delete-orphan-was-no-longer-referenced-by-the-owning-entity-instance


5.2. データベースアクセス(JPA編

5.2.2.11. Entityの削除処理の実装

https://terasolunaorg.github.io/guideline/public_review/ArchitectureInDetail/DataAccessJpa.html#id38


JPAについて調べてみた

http://juzow.hatenablog.com/entry/20121017/1350480972