【问题标题】:Cascades settings in JPA and foreign key violation in hibernateJPA 中的级联设置和休眠中的外键冲突
【发布时间】:2014-02-26 04:41:49
【问题描述】:

我有两门课:

  1. 父母
  2. 孩子

在数据库子表中有一列ParentId -> 典型的One(Parent)-> Many(Children)关系

现在我创建了两个实体,它们

public class Parent
{
    @OneToMany(mappedBy="Parent", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    public Set<Child> getChildern()
    {
      ...
    }
}

public class Child
{
   @ManyToOne(fetch = FetchType.EAGER, cascade=CascadeType.ALL)
   @JoinColumn(name="ParentId")
   public Parent getParent()
   { ... }
}

现在我有两种情况:

  1. 父级被删除 -> 会发生什么?
  2. 孩子被删除 -> 会发生什么?

额外问题:

  1. 我是否总是需要创建密钥 OneToMany 和 ManyToOne 的两个部分,或者我可以只创建 ManyToOne 并且不在乎我有孩子的父母吗?
  2. 什么可能导致休眠给我一个消息外键约束违反没有孩子的父母?

【问题讨论】:

标签: java hibernate jpa cascade entities


【解决方案1】:

首先,我很惊讶这段代码能正常工作。 IMO mappedBy="Parent" 实际上应该是 mappedBy="parent"(注意小写的“p”),因为 Child 类的父属性称为 parent 而不是 Parent

其次,我建议您将注释放在属性上而不是访问器方法上。我发现它构成了整个代码

您的问题的答案取决于您所说的“被删除”究竟是什么意思。我假设您的意思是“通过持久性管理器删除”。

但是,如果您希望/希望 JPA 提供程序删除一个孩子,如果您执行 parent.getChildren().remove(x),那么您需要在 OneToMany 上设置 orphanRemoval = "true"

问题 1

父项和所有子项都将被删除。这是常见的情况。

问题 2

父项和所有子项都将被删除。这是一个相当奇怪的用例。通常级联删除只适用于一对多关系。

奖金 1

Java 和 JPA 中的所有关系都是单向的,如果一个 源对象引用了目标对象,不能保证 目标对象也与源对象有关系。

来自优秀的Java Persistence wiki book

奖金 2

不知道。 ConstraintViolationException 是否来自底层数据库?或者换一种说法,这两个表的 DDL 是什么样子的?它是由 Hibernate 生成的吗?

【讨论】:

  • 这是一个为了简单起见而制作的示例代码,你还没有看到我的私有字段是如何被调用的。没有生成查询,休眠中断,当我自己使用 id 生成删除查询时,一切都很好。我实际上想禁止任何自动 cascasion,我应该使用哪些设置然后 parent = persist,child = nothing?
  • 关于奇怪的双方没有关系,想象你有 5 个父类型的实体和 100000 个子类型的实体,即使有一个lazy_loading 它也是一个杀手。我用过滤很多的特定查询加载孩子。
  • “想要禁止任何自动级联” - 然后不要定义它。如果省略cascade 参数nothing happens。但是,我想您真正想要的是孩子总是自动持久化,对吧?然后在ManyToOne 中省略cascade 并在OneToMany 中设置cascade = CascadeType.PERSIST
  • 这就是我所做的:)
  • 现在怎么样,一切都好吗?如果您将 4 个问题打包成 1 个问题,真的很难知道您的问题是否得到解决。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-15
  • 1970-01-01
  • 2014-03-17
  • 1970-01-01
  • 1970-01-01
  • 2010-12-31
相关资源
最近更新 更多