3

所以我的休眠实现有问题。当我尝试删除父类时,在级联层次结构深处的类上收到外键约束异常。在详细介绍之前,我将首先描述类的关系,因为它关系到它们需要如何保存和删除。

在顶层,我有一个 Customer 类,其中包含一个 DefaultMask 对象列表。这是主列表,因为这些默认掩码由我的对象层次结构中的其他类使用,但始终来自此列表。仅在此列表中创建掩码并从此列表中删除。

在层次结构的更下方,我有一个 Column 类,它可以(可选地)在其上设置一个 DefaultMask。更简洁地描述这种关系;

客户拥有零到多个 DefaultMask。客户拥有零到多列。一列可能有一个 DefaultMask。

在我的应用程序中,当我尝试删除客户时,异常来自 Column 类到 DefaultMask 类的外键约束,我认为问题在于 CascadeType 的设置不正确。我已经研究了这个问题并找到了关于名为 mappedBy 的属性和使用 Hibernate 自己的 CascadeType.SAVE_UPDATE 的信息(为了防止 Hibernate 尝试删除由 Column 持有的 DefaultMask),但我承认我在这里有点迷路并且可以使用一些直接的指导。类的相关代码和实际的异常消息如下。

顾客:

@Entity
public class Customer {

@Id
private String id;
@OneToMany(cascade = CascadeType.ALL)
private List<DefaultMask> masks;
    //(Columns are held further down in hierarchy)

柱子:

@Entity
@Table(name = "WarehouseColumn")
public class Column implements Comparable<Column> {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int hibernateID;
@OneToOne
private DefaultMask mask;

默认掩码:

@Entity
public class DefaultMask implements Mask {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int hibernateID;
private String type;
private String mask;

异常消息:

org.hibernate.exception.ConstraintViolationException: 无法删除或更新父行:外键约束失败( hibernate. WarehouseColumn, CONSTRAINT FK8BB153D994AD57D3FOREIGN KEY ( mask_hibernateID) REFERENCES DefaultMask( hibernateID)) 原因:com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: 无法删除或更新父行:外键约束失败 ( hibernate. WarehouseColumn, CONSTRAINT FK8BB153D994AD57D3FOREIGN KEY ( mask_hibernateID) REFERENCES DefaultMask( hibernateID))

4

2 回答 2

1

级联与逻辑所有权的概念密切相关。

基本上,您需要选择以下选项之一:

  • Customer逻辑上拥有它DefaultMask的 s。在这种情况下,您希望DefaultMask在删除 a 时删除 s Customer,因此您需要使用CascadeType.ALL. 由于Columnreferences DefaultMask,它可能也属于Customer,并且应该删除到

    它可以通过使用适当的级联之间的双向关系来实现DefaultMaskColumn如下所示:

    @Entity
    public class DefaultMask implements Mask {
        @OneToOne(mappedBy = "mask", cascade = CascadeType.ALL)
        Column column;
        ...
    }
    
  • DefaultMasks 本身就是实体,Customer仅引用现有DefaultMask的 s。在这种情况下,您可能根本不需要对这种关系使用级联。

于 2012-11-05T11:43:26.513 回答
1

您正试图删除一个客户,这会自动删除其默认掩码列表。但是其中一个掩码被一列引用。所以数据库(以及 Hibernate)拒绝执行删除,因为它会使列处于不一致的状态:它会引用一个不再存在的默认掩码。

所以你有几个功能选择:

  • 保持原样:无法删除客户,因为其掩码之一仍被列引用
  • 删除级联:删除客户将删除客户,但不会删除其掩码。
  • 找到所有引用要删除的用户的任何默认掩码的列,并删除这些列。然后,删除用户及其默认掩码
  • 查找所有引用要删除的用户的任何默认掩码的列,并将其掩码字段设置为空。然后,删除用户及其默认掩码
于 2012-11-05T11:43:56.877 回答