JPA:单向多对一和级联删除

时间:2011-08-25 21:06:43

标签: java jpa jpa-2.0 many-to-one

说我有一个单向 @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 ... C n 引用回P,那么在JPA中有一个干净漂亮的方法可以自动删除当P被移除时(即entityManager.remove(P)),子C 1 ... C n

我正在寻找的功能类似于SQL中的ON DELETE CASCADE

7 个答案:

答案 0 :(得分:72)

如果您使用hibernate作为JPA提供程序,则可以使用注释@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 之类的查询也将删除子节点。

答案 1 :(得分:66)

JPA中的关系始终是单向的,除非您在两个方向上将父级与子级相关联。从父母到孩子的级联REMOVE操作将需要从父母到孩子的关系(而不仅仅是相反的)。

因此,您需要这样做:

  • 或者,将单向@ManyToOne关系更改为双向@ManyToOne或单向@OneToMany。然后,您可以级联REMOVE操作,以便EntityManager.remove将删除父项和子项。您还可以将orphanRemoval指定为true,以便在父集合中的子实体设置为null时删除任何孤立子项,即删除子项在任何父项集合中不存在时的子项。
  • 或者,将子表中的外键约束指定为ON DELETE CASCADE。在调用EntityManager.clear()之后,您需要调用EntityManager.remove(parent),因为需要刷新持久性上下文 - 在数据库中删除后,子实体不应该存在于持久性上下文中。 / LI>

答案 2 :(得分:13)

创建双向关系,如下所示:

@Entity
public class Parent implements Serializable {

    @Id
    @GeneratedValue
    private long id;

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

答案 3 :(得分:0)

我在单向@ManytoOne中看到过,删除无法正常工作。 删除父级后,理想情况下也应删除子级,但仅删除父级,不删除子级,而将其保留为孤儿

使用的技术是Spring Boot / Spring Data JPA / Hibernate

Sprint引导:2.1.2。释放

Spring Data JPA / Hibernate用于删除行。例如

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;


}

答案 4 :(得分:0)

使用这种方式仅删除一侧

    @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;

答案 5 :(得分:-1)

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

鉴于注释对我有用。可以尝试一下

例如: -

     public class Parent{
            @Id
            @GeneratedValue(strategy=GenerationType.AUTO)
            @Column(name="cct_id")
            private Integer cct_id;
            @OneToMany(cascade=CascadeType.REMOVE, fetch=FetchType.EAGER,mappedBy="clinicalCareTeam", orphanRemoval=true)
            @Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
            private List<Child> childs;
        }
            public class Child{
            @ManyToOne(fetch=FetchType.EAGER)
            @JoinColumn(name="cct_id")
            private Parent parent;
    }

答案 6 :(得分:-1)

您不需要使用双向关联而不是代码,只需将CascaType.Remove作为属性添加到ManyToOne批注中,然后使用@OnDelete(action = OnDeleteAction.CASCADE),对于我。