所以我的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:无法删除或更新父行:外键约束失败(hibernate
。WarehouseColumn
,CONSTRAINT FK8BB153D994AD57D3
FOREIGN KEY({{1} })参考mask_hibernateID
(DefaultMask
))
引起:com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException:无法删除或更新父行:外键约束失败(hibernateID
。hibernate
,CONSTRAINT WarehouseColumn
FOREIGN KEY( FK8BB153D994AD57D3
)参考mask_hibernateID
(DefaultMask
))
答案 0 :(得分:1)
级联与逻辑所有权的概念密切相关。
基本上,您需要选择以下选项之一:
Customer
逻辑上拥有其DefaultMask
s。在这种情况下,您希望在删除DefaultMask
时删除Customer
,因此您需要使用CascadeType.ALL
。由于Column
引用DefaultMask
,它可能也归Customer
所有,应该删除
可以通过使用适当级联的DefaultMask
和Column
之间的双向关系来实现,如下所示:
@Entity
public class DefaultMask implements Mask {
@OneToOne(mappedBy = "mask", cascade = CascadeType.ALL)
Column column;
...
}
DefaultMask
是自己的实体,Customer
只引用现有的DefaultMask
。在这种情况下,您可能根本不需要使用级联来实现此关系。
答案 1 :(得分:1)
您正急于删除一个客户,该客户会自动删除其默认掩码列表。但是这些掩码中的一个是由列引用的。因此数据库(以及Hibernate)拒绝执行删除,因为它会使列处于不一致状态:它将引用不再存在的默认掩码。
所以你有几个功能选择: