简体   繁体   English

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

[英]JPA: unidirectional many-to-one and cascading delete

Say I have a unidirectional @ManyToOne relationship like the following:假设我有一个单向@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;  
}

If I have a parent P and children C 1 ...C n referencing back to P, is there a clean and pretty way in JPA to automatically remove the children C 1 ...C n when P is removed (ie entityManager.remove(P) )?如果我有一个父 P 和子 C 1 ...C n引用回 P,那么 JPA 中是否有一种干净漂亮的方法可以在删除 P 时自动删除子 C 1 ...C n (即entityManager.remove(P) )?

What I'm looking for is a functionality similar to ON DELETE CASCADE in SQL.我正在寻找的是类似于 SQL 中的ON DELETE CASCADE的功能。

If you are using hibernate as your JPA provider you can use the annotation @OnDelete .如果你使用 hibernate 作为你的 JPA 提供者,你可以使用注解@OnDelete This annotation will add to the relation the trigger ON DELETE CASCADE , which delegates the deletion of the children to the database.此注释将向关系添加触发器ON DELETE CASCADE ,它将子项的删除委托给数据库。

Example:例子:

public class Parent {
   
        @Id
        private long id;

}


public class Child {
        
        @Id
        private long id;
  
        @ManyToOne
        @OnDelete(action = OnDeleteAction.CASCADE)
        private Parent parent;
}
     

With this solution a unidirectional relationship from the child to the parent is enough to automatically remove all children.使用此解决方案,从子级到父级的单向关系足以自动删除所有子级。 This solution does not need any listeners etc. Also a JPQL query like DELETE FROM Parent WHERE id = 1 will remove the children.此解决方案不需要任何侦听器等。此外,像DELETE FROM Parent WHERE id = 1这样的 JPQL 查询将删除子级。

Relationships in JPA are always unidirectional, unless you associate the parent with the child in both directions. JPA 中的关系始终是单向的,除非您在两个方向上将父级与子级关联起来。 Cascading REMOVE operations from the parent to the child will require a relation from the parent to the child (not just the opposite).从父级到子级的级联 REMOVE 操作将需要从父级到子级的关系(而不仅仅是相反)。

You'll therefore need to do this:因此,您需要这样做:

  • Either, change the unidirectional @ManyToOne relationship to a bi-directional @ManyToOne , or a unidirectional @OneToMany .或者,将单向@ManyToOne关系更改为双向@ManyToOne或单向@OneToMany You can then cascade REMOVE operations so that EntityManager.remove will remove the parent and the children.然后,您可以级联 REMOVE 操作,以便EntityManager.remove将删除父项和子项。 You can also specify orphanRemoval as true, to delete any orphaned children when the child entity in the parent collection is set to null, ie remove the child when it is not present in any parent's collection.您还可以将orphanRemoval指定为 true,以在父集合中的子实体设置为 null 时删除任何孤立的子实体,即当子实体不存在于任何父集合中时删除子实体。
  • Or, specify the foreign key constraint in the child table as ON DELETE CASCADE .或者,将子表中的外键约束指定为ON DELETE CASCADE You'll need to invoke EntityManager.clear() after calling EntityManager.remove(parent) as the persistence context needs to be refreshed - the child entities are not supposed to exist in the persistence context after they've been deleted in the database.您需要在调用EntityManager.remove(parent) EntityManager.clear()之后调用 EntityManager.clear(),因为需要刷新持久性上下文 - 子实体在数据库中被删除后不应该存在于持久性上下文中。

Create a bi-directional relationship, like this:创建双向关系,如下所示:

@Entity
public class Parent implements Serializable {

    @Id
    @GeneratedValue
    private long id;

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

I have seen in unidirectional @ManytoOne, delete don't work as expected.我在单向@ManytoOne 中看到,删除不能按预期工作。 When parent is deleted, ideally child should also be deleted, but only parent is deleted and child is NOT deleted and is left as orphan删除父级时,理想情况下也应删除子级,但仅删除父级,不删除子级并保留为孤儿

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

Sprint Boot : 2.1.2.RELEASE冲刺启动:2.1.2.RELEASE

Spring Data JPA/Hibernate is used to delete row .eg Spring Data JPA/Hibernate 用于删除行.eg

parentRepository.delete(parent)

ParentRepository extends standard CRUD repository as shown below ParentRepository extends CrudRepository<T, ID> ParentRepository 扩展标准 CRUD 存储库,如下所示ParentRepository extends CrudRepository<T, ID>

Following are my entity class以下是我的实体类

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


}

用这种方式只删除一侧

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

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

Given annotation worked for me.给定注释对我有用。 Can have a try可以试一试

For Example :-例如 :-

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM