109

假设我有一个单向 @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 时自动删除子 C 1 ...C n(即entityManager.remove(P))?

我正在寻找的是类似于ON DELETE CASCADESQL 的功能。

4

7 回答 7

114

如果您使用 hibernate 作为您的 JPA 提供者,您可以使用 annotation @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;
}
     

使用此解决方案,从子级到父级的单向关系足以自动删除所有子级。此解决方案不需要任何侦听器等。此外,JPQL 查询之类DELETE FROM Parent WHERE id = 1的将删除子级。

于 2016-07-21T04:59:03.870 回答
77

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

因此,您需要这样做:

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

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

@Entity
public class Parent implements Serializable {

    @Id
    @GeneratedValue
    private long id;

    @OneToMany(mappedBy = "parent", cascade = CascadeType.REMOVE)
    private Set<Child> children;
}
于 2012-06-18T01:28:19.100 回答
2

我在单向@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;


}
于 2019-02-11T15:57:03.810 回答
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;
于 2019-09-09T13:47:17.083 回答
-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;
    }
于 2016-02-25T09:29:56.767 回答
-1

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

于 2020-09-18T01:52:44.167 回答