当前位置: 首页 > 知识库问答 >
问题:

孤立删除在hibernate中无法正常工作:从列表中插入和删除的元素在数据库中保持不变

百里景山
2023-03-14

我们有一个问题,听起来像Hibernate中处理oneToMany列表(带索引)的orphanRemovation=true的bug。

以下是简化的映射:

public class ParentClass {

  [...]

  @OneToMany(cascade = ALL, mappedBy = "parent", orphanRemoval = true)
  @OnDelete(action = OnDeleteAction.CASCADE)
  @Fetch(FetchMode.JOIN)
  @OrderColumn(name = "pos", nullable = false)
  public List<ChildClass> getChildren() {
    return children;
  }

}

儿童班:

public class ChildClass {
    [...]

    @ManyToOne
    @JoinColumn(nullable = false, name = "parent_id")
    public ParentClass getParent() {
        return parent;
    } 
}

鉴于此映射,以下场景将失败:

  1. 从DB获取父节点
  2. 给它加一个孩子
  3. 从DB(不是同一个实体)获取其他东西,产生部分同花顺
  4. 从父节点上移除子节点
  5. 离开交易

这是密码

@Transactional
public void test() {

  // 1)
  ParentClass parent = entityManager.find(ParentClass.class, "some-id");

  // 2)
  ChildClass child = new ChildClass(parent);
  parent.getChildren().add(child);

  // 3)
  entityManager.find(SomethingElse.class, "2");

  // 4)
  parent.getChildren().remove(child);  
}

在这种情况下,子分配被插入到DB中,并且在事务结束时不被删除。

但是,如果不执行步骤3),则子分配不会正确地持久化到数据库

那是虫子吗?错误的映射?有解决办法吗?

共有3个答案

张岳
2023-03-14

有一个JPA注释@PreRemove可能对您的特定情况有所帮助。尝试将其添加到子实体,以便它可以从父实体中删除自己:

@PreRemove
protected void beforeRemove(){
    parent.getChildren().remove(this);
}
柯新翰
2023-03-14

删除子项时,需要设置关联的双方:

child.setParent(null);
parent.getChildren().remove(child);  

在你的情况下,孤儿转移是不够的。如果一对多是单向关联,那么您可以简单地从列表中删除孩子,删除将传播到孩子实体。

当你有双向关联时,你需要双方同步。这就是为什么在删除时需要将子实体与父实体解除关联。

符畅
2023-03-14

是的,那是一只虫子。我打赌您没有使用Hibernate的最新版本(4.3.8),并且它与此问题相关(如果不是同一问题):[HHH-9330]orphanRemove=true在双向关系中不起作用(没有级联),即使使用最新版本,此错误也可能存在。如果是这样,请报告它,然后在这里的某个地方向bug报告URL。解决方法:仅当确定必须持久化子项时,才尝试添加该子项,或者尝试将子项中的父项设置为null:

child.setParent(空)

另外,作为另一种解决方法,您可以尝试使用Hibernate会话,而不是EntityManager(正如Hibernate论坛中所写)。

 类似资料:
  • 问题内容: 我正在尝试清理有很多孤立物品的桌子。 我正在通过查找空值来检查是否与另一个表有关系,从而达到这一目的。 我收到一个错误,左外部联接无效。 我正在寻找其他方法的建议,可以从这种破裂的关系中删除这些孤儿 问题答案: 试试这个:

  • 问题内容: 阅读了 JPA 2.0 / Hibernate和“orphanRemoval”:仅替换一个实体并不会删除旧的实体和相关票据https://hibernate.atlassian.net/browse/HHH-6484,我推断这已经(最终是)已在4.2.7和4.3.0.CR1版中修复。 但是,尝试 哪里 仍然不会使Hibernate 为目标实体发出SQL语句。 那么,此问题是否已解决?如

  • 当单击按钮时,我试图删除表中的数据行。我当前的代码在1-3次按下后删除行内容,但我希望它能清除内容,然后在一次按下中添加新内容。 这是我正在使用的代码。。。 5行数据显示在jTable中。再次按下按钮后,将删除两行数据。如果我按下按钮,第二次留下一行数据。第三次按下按钮,所有行都被删除,下一次按下按钮将插入5行数据。理想情况下,我希望这个按钮总是清除行字段,然后添加插入的数据。使每个按钮按下显示新

  • 问题内容: 从列表中删除项目时遇到麻烦。该列表是在超类中定义的,但是Hibernate批注将应用于子类中的属性访问器。超类中有两种方法可以操作列表。“添加”方法可以正常工作,但“删除”不能持久保存更改。我检查了我的Cascade设置,似乎一切正确。我在做一些不可能的事情吗?如果不是,我做错了什么吗? 这是我的课程: 我按如下方式使用TemporalAsset类的实例(请注意,我仅使用“refres

  • 我刚加入弹性搜索公司。我正在想办法从ElasticSearch中删除数据。我已经删除了我的索引。然而,这似乎并没有真正删除数据本身。我看到的其他内容指向Delete by Query特性。然而,我甚至不确定该查询什么。我知道我的索引。从本质上说,我想弄清楚如何做一个 来自Chrome版邮递员。但是,我没有什么运气。好像不管我做什么,数据都挂在那里。到目前为止,我已经通过使用PostMan中的DEL

  • 在mysql工作台中,我试图执行 这是一个查询,但是我收到了这个消息 错误代码:1175。您使用的是安全更新模式,并且您试图更新一个没有使用键列禁用安全模式的表,请在“首选项”中切换该选项-