简体   繁体   English

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

[英]Getting Hibernate to cascade on save, but not delete?

So I'm having a problem with my hibernate implementation. 所以我的hibernate实现有问题。 When I try to delete a parent class, I receive a foreign key constraint exception on a class deep within the cascade hierarchy. 当我尝试删除父类时,我在级联层次结构深处的类上收到外键约束异常。 Before I go into specifics, I'll first describe the relationships of the classes, as it has a bearing on how they need to be saved and deleted. 在我详细介绍之前,我将首先描述类的关系,因为它与它们如何被保存和删除有关。

At the top level, I have a Customer class, which contains a list of DefaultMask objects. 在顶层,我有一个Customer类,其中包含一个DefaultMask对象列表。 This is the master list, in that these default masks are used by other classes in my object hierarchy, but always from this list. 这是主列表,因为这些默认掩码由我的对象层次结构中的其他类使用,但始终来自此列表。 Masks are only created into this list and deleted from this list. 掩码仅创建到此列表中并从此列表中删除。

Further down the hierarchy, I have a Column class, which can (optionally) have a DefaultMask set on it. 在层次结构的下面,我有一个Column类,它可以(可选)在其上设置DefaultMask。 To describe the relationship more succinctly; 更简洁地描述这种关系;

A Customer OWNS zero to many DefaultMasks. 客户OWNS零到多个DefaultMasks。 A Customer OWNS zero to many Columns. 客户OWNS零到多列。 A Column may have one DefaultMask. 列可以有一个DefaultMask。

In my application, when I attempt to delete a Customer, the exception comes from the foreign-key constraint on the Column class to the DefaultMask class, and I believe the problem is incorrect settings with CascadeType. 在我的应用程序中,当我尝试删除Customer时,异常来自Column类的外键约束到DefaultMask类,我相信问题是CascadeType的设置不正确。 I have researched the problem and found information on an attribute called mappedBy and on using Hibernate's own CascadeType.SAVE_UPDATE (in order to prevent Hibernate trying to delete a DefaultMask held by a Column), but I will admit I am a bit lost here and could use some direct guidance. 我已经研究了这个问题并找到了一个名为mappedBy的属性和使用Hibernate自己的CascadeType.SAVE_UPDATE的信息(为了防止Hibernate试图删除一个Column所持有的DefaultMask),但我承认我在这里有点迷失了使用一些直接指导。 Relevant code for the classes and the actual exception message are below. 类的相关代码和实际的异常消息如下所示。

Customer: 顾客:

@Entity
public class Customer {

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

Column: 柱:

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

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

DefaultMask: DefaultMask:

@Entity
public class DefaultMask implements Mask {

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

Exception message: 异常消息:

org.hibernate.exception.ConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails ( hibernate . WarehouseColumn , CONSTRAINT FK8BB153D994AD57D3 FOREIGN KEY ( mask_hibernateID ) REFERENCES DefaultMask ( hibernateID )) Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails ( hibernate . WarehouseColumn , CONSTRAINT FK8BB153D994AD57D3 FOREIGN KEY ( mask_hibernateID ) REFERENCES DefaultMask ( hibernateID )) org.hibernate.exception.ConstraintViolationException:不能删除或更新父行,外键约束失败( hibernateWarehouseColumn ,约束FK8BB153D994AD57D3外键( mask_hibernateID )参考文献DefaultMaskhibernateID ))产生的原因:com.mysql.jdbc.exceptions。 jdbc4.MySQLIntegrityConstraintViolationException:不能删除或更新父行,外键约束失败( hibernateWarehouseColumn ,约束FK8BB153D994AD57D3外键( mask_hibernateID )引用DefaultMaskhibernateID ))

Cascading is closely related to the concept of logical ownership. 级联与逻辑所有权的概念密切相关。

Basically, you need to choose one of the following options: 基本上,您需要选择以下选项之一:

  • Customer logically owns its DefaultMask s. Customer逻辑上拥有其DefaultMask In this case you want DefaultMask s to be deleted when you delete a Customer , therefore you need to use CascadeType.ALL . 在这种情况下,您希望在删除Customer时删除DefaultMask ,因此您需要使用CascadeType.ALL Since Column references DefaultMask , it's probably owned by Customer as well, and should be deleted to 由于Column引用了DefaultMask ,它可能也归Customer所有,应该删除

    It can be achieved by using bidirectional relationship between DefaultMask and Column with appropriate cascading, as follows: 它可以通过使用DefaultMaskColumn之间的双向关系以及适当的级联来实现,如下所示:

     @Entity public class DefaultMask implements Mask { @OneToOne(mappedBy = "mask", cascade = CascadeType.ALL) Column column; ... } 
  • DefaultMask s are entities on its own, and Customer just references existing DefaultMask s. DefaultMask是它们自己的实体, Customer只引用现有的DefaultMask In this case you probably don't need to use cascading for this relationship at all. 在这种情况下,您可能根本不需要使用级联来实现此关系。

You're rying to delete a customer, which automatically deletes its list of default masks. 您正急于删除一个客户,该客户会自动删除其默认掩码列表。 But one of these masks is referenced by a column. 但是这些掩码中的一个是由列引用的。 So the database (and thus Hibernate) refuses to execute the deletion, because it would leave the column in an inconsistent state: it would reference a default mask that doesn't exist anymore. 因此数据库(以及Hibernate)拒绝执行删除,因为它会使列处于不一致状态:它将引用不再存在的默认掩码。

So you have several functional choices: 所以你有几个功能选择:

  • leave it as it is: the customer can't be deleted because one of its masks is still referenced by a column 保持原样:无法删除客户,因为其中一个掩码仍由列引用
  • remove the cascade: deleting the customer will delete the customer but not its masks. 删除级联:删除客户将删除客户但不删除其掩码。
  • find all the columns which reference any of the default masks of the user to be deleted, and remove these columns. 找到引用要删除的用户的任何默认掩码的所有列,并删除这些列。 Then, remove the user and its default masks 然后,删除用户及其默认掩码
  • find all the columns which reference any of the default masks of the user to be deleted, and set their mask fild to null. 找到引用要删除的用户的任何默认掩码的所有列,并将其掩码fild设置为null。 Then, remove the user and its default masks 然后,删除用户及其默认掩码

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

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