首页 > 解决方案 > 休眠:一对多关系的级联删除问题

问题描述

我有以下实体模型。

@Entity
@Table(name="product")
public class ProductEntity {
      @Id
      @GeneratedValue(generator = "uuid2")
      @GenericGenerator(name = "uuid2", strategy = "uuid2")
      private UUID id;

      ...


      @OneToMany(mappedBy = "productEntity", cascade = CascadeType.ALL)
      private List<ProductAddonEntity> productAddonEntities;
 }


@Entity
@Table(name="product_addon")
public class ProductAddonEntity {
      @Id
      @GeneratedValue(generator = "uuid2")
      @GenericGenerator(name = "uuid2", strategy = "uuid2")
      private UUID id;

      ...


      @ManyToOne()
      @JoinColumn(name = "addon_id")
      private ProductEntity addonEntity;
 }

我想删除产品,并且该删除还应删除与该产品相关的所有 ProductAddon 实体。所以我声明了与所有级联类型的一对多关系。但是当我尝试删除某些产品时,Hibernate 一开始会尝试在 product_addon 表中设置 null addon_id。但是该列具有非空约束,因此删除失败。

所以我添加到注释@ManyToOne 参数

    @JoinColumn(name = "addon_id", nullable = false, updatable = false)

但是现在休眠只是尝试删除产品,然后再删除与该产品相关的 product_addon 实体。由于外键约束,此删除失败(无法删除或更新父行:外键约束失败)。

这里有什么问题?此应用程序还使用 liquibase,因此外键不是由 hibernate 生成的。例如,addon_id 的外键没有删除操作,但我认为休眠不需要这些操作,因为它适用于更高的数据层

标签: sqlhibernatehibernate-cascade

解决方案


孤儿删除是一种激进的删除级联模式,用于在需要删除父对象时删除子对象(@OneToOne 和 @OneToMany 关系)。此功能从 JPA 2.0 版本添加。JPA 删除操作

两种设置之间的区别在于对断开关系的响应。例如,当将地址字段设置为空或另一个地址对象时。

@Entity   
class Employee {

@OneToOne(cascade=CascadeType.REMOVE)
private Address address;

}

如果仅指定了 cascade=CascadeType.REMOVE,则不会采取自动操作,因为断开关系不是删除操作。

@Entity
class Employee {

@OneToOne(orphanRemoval=true)
private Address address;

}

如果指定了 orphanRemoval=true,则断开连接的 Address 实例将被自动删除。这对于清理在没有来自所有者对象(例如 Employee)的情况下不应该存在的依赖对象(例如地址)很有用。


推荐阅读