web-dev-qa-db-ja.com

JPA:単方向の多対1およびカスケード削除

次のような単方向 _@ManyToOne_の関係があるとします。

_@Entity
public class Parent implements Serializable {

    @Id
    @GeneratedValue
    private long id;
}

@Entity
public class Child implements Serializable {

    @Id
    @GeneratedValue
    private long id;

    @ManyToOne
    @JoinColumn
    private Parent parent;  
}
_

親Pと子Cがある場合1... Cn Pを参照し直しますが、JPAには子Cを自動的に削除するきれいできれいな方法がありますか1... Cn Pが削除されたとき(つまりentityManager.remove(P))?

私が探しているのは、SQLの_ON DELETE CASCADE_に似た機能です。

83
perp

JPAの関係は、親と子を双方向で関連付けない限り、常に単方向です。親から子へのカスケードREMOVE操作では、親から子へのリレーションが必要になります(逆ではありません)。

したがって、これを行う必要があります。

  • 単方向の_@ManyToOne_関係を双方向の_@ManyToOne_または単方向の_@OneToMany_に変更します。その後、 _EntityManager.remove_ が親と子を削除するように、REMOVE操作をカスケードできます。 orphanRemoval をtrueに指定して、親コレクションの子エンティティがnullに設定されている場合、孤立した子を削除する、つまり、子が親の子に存在しない場合は削除することもできますコレクション。
  • または、子テーブルの外部キー制約を_ON DELETE CASCADE_として指定します。永続コンテキストを更新する必要があるため、 EntityManager.clear() を呼び出した後、 EntityManager.remove(parent) を呼び出す必要があります-子エンティティはデータベースから削除された後、永続コンテキストに存在することになっています。
66
Vineet Reynolds

JPAプロバイダーとしてhibernateを使用している場合、アノテーション@OnDeleteを使用できます。このアノテーションは、リレーションにトリガーON DELETE CASCADEを追加します。これは、子の削除をデータベースに委任します。

例:

public class Parent {

        @Id
        private long id;

}


public class Child {

        @Id
        private long id;

        @ManyToOne
        @OnDelete(action = OnDeleteAction.CASCADE)
        private Parent parent;
}

このソリューションでは、すべての子を自動的に削除するには、子から親への一方向の関係で十分です。このソリューションはリスナーなどを必要としません。また、DELETE FROM Parent WHERE id = 1のようなクエリは子を削除します。

77
Thomas Hunziker

次のような双方向の関係を作成します。

@Entity
public class Parent implements Serializable {

    @Id
    @GeneratedValue
    private long id;

    @OneToMany(mappedBy = "parent", cascade = CascadeType.REMOVE)
    private Set<Child> children;
}
12
tekumara

単方向の@ManytoOneで、削除が期待どおりに機能しないことを確認しました。親を削除する場合、理想的には子も削除する必要がありますが、親のみが削除され、子は削除されず、孤立したままになります

使用されるテクノロジーは、Spring Boot/Spring Data JPA/Hibernateです。

スプリントブート:2.1.2.RELEASE

Spring Data JPA/Hibernateは、行.egを削除するために使用されます

parentRepository.delete(parent)

ParentRepositoryは、以下に示すように標準のCRUDリポジトリを拡張しますParentRepository extends CrudRepository<T, ID>

以下は私のエンティティクラスです

@Entity(name = “child”)
public class Child  {

    @Id
    @GeneratedValue
    private long id;

    @ManyToOne( fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = “parent_id", nullable = false)
    @OnDelete(action = OnDeleteAction.CASCADE)
    private Parent parent;
}

@Entity(name = “parent”)
public class Parent {

    @Id
    @GeneratedValue
    private long id;

    @Column(nullable = false, length = 50)
    private String firstName;


}
0
ranjesh