让Hibernate在保存时级联,但不能删除?

时间:2012-11-05 11:29:37

标签: java hibernate cascade

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

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

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

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

在我的应用程序中,当我尝试删除Customer时,异常来自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;

DefaultMask:

@Entity
public class DefaultMask implements Mask {

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

异常消息:

org.hibernate.exception.ConstraintViolationException:无法删除或更新父行:外键约束失败(hibernateWarehouseColumn,CONSTRAINT FK8BB153D994AD57D3 FOREIGN KEY({{1} })参考mask_hibernateIDDefaultMask)) 引起:com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException:无法删除或更新父行:外键约束失败(hibernateIDhibernate,CONSTRAINT WarehouseColumn FOREIGN KEY( FK8BB153D994AD57D3)参考mask_hibernateIDDefaultMask))

2 个答案:

答案 0 :(得分:1)

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

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

  • Customer逻辑上拥有其DefaultMask s。在这种情况下,您希望在删除DefaultMask时删除Customer,因此您需要使用CascadeType.ALL。由于Column引用DefaultMask,它可能也归Customer所有,应该删除

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

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

答案 1 :(得分:1)

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

所以你有几个功能选择:

  • 保持原样:无法删除客户,因为其中一个面具仍由列引用
  • 删除级联:删除客户将删除客户,但不删除其掩码。
  • 找到引用要删除的用户的任何默认掩码的所有列,并删除这些列。然后,删除用户及其默认掩码
  • 找到引用要删除的用户的任何默认掩码的所有列,并将其掩码fild设置为null。然后,删除用户及其默认掩码