我有以下问题时,试图更新我的实体:

"A collection with cascade=”all-delete-orphan” was no longer referenced by the owning entity instance".

我有一个父实体,它有一个Set<…>的子实体。当我尝试更新它时,我得到了要设置到这个集合的所有引用并设置它。

下面的代码表示我的映射:

@OneToMany(mappedBy = "parentEntity", fetch = FetchType.EAGER)
@Cascade({ CascadeType.ALL, CascadeType.DELETE_ORPHAN })
public Set<ChildEntity> getChildren() {
    return this.children;
}

我已经尝试清理Set<..只有>,根据这个:如何“可能”解决问题,但它没有工作。

如果你有什么想法,请告诉我。

谢谢!


当前回答

我有同样的问题,但它是当集合为空。只有在Set集合中,在List中工作正常。您可以尝试使用hibernate注释@LazyCollection(LazyCollectionOption.FALSE)而不是JPA注释fetch = FetchType.EAGER。

我的解决方案: 这是我的配置和工作良好

@OneToMany(mappedBy = "format", cascade = CascadeType.ALL, orphanRemoval = true)
@LazyCollection(LazyCollectionOption.FALSE)
private Set<Barcode> barcodes;

@OneToMany(mappedBy = "format", cascade = CascadeType.ALL, orphanRemoval = true)
@LazyCollection(LazyCollectionOption.FALSE)
private List<FormatAdditional> additionals;

其他回答

另一个原因可能是使用龙目岛。

@Builder -导致保存Collections.emptyList(),即使你说.myCollection(new ArrayList());

@Singular -忽略类级别的默认值,并保留字段为空,即使类字段声明为myCollection = new ArrayList()

我的2美分,刚刚花了2个小时在同样的东西上:)

@OneToMany(mappedBy = 'parent', cascade= CascadeType.ALL, orphanRemoval = true)
List<Child> children = new ArrayList<>();

当我将子对象添加到现有的子对象列表中时,我遇到了相同的错误。

childService.saveOrUpdate(child);
parent.addToChildren(child);
parentService.saveOrUpdate(parent);

解决我问题的是:

child = childService.saveOrUpdate(child);

现在孩子复活了其他细节以及它工作得很好。

当我在很多地方读到hibernate不喜欢你给一个集合赋值时,我认为最安全的做法显然是让它像这样成为final:

class User {
  private final Set<Role> roles = new HashSet<>();

public void setRoles(Set<Role> roles) {
  this.roles.retainAll(roles);
  this.roles.addAll(roles);
}
}

然而,这不起作用,您会得到可怕的“不再引用”错误,在这种情况下,这实际上是相当具有误导性的。

结果是hibernate调用setRoles方法,并且它希望在这里安装它的特殊集合类,并且不接受您的集合类。尽管阅读了所有关于不要在set方法中给集合赋值的警告,我还是被这个问题难住了很长一段时间。

所以我改成了这个:

public class User {
  private Set<Role> roles = null;

  public void setRoles(Set<Role> roles) {
  if (this.roles == null) {
    this.roles = roles;
  } else {
    this.roles.retainAll(roles);
   this.roles.addAll(roles);
  }
}
}

因此,在第一次调用时,hibernate安装它的特殊类,在随后的调用中,您可以自己使用该方法,而不会破坏任何东西。如果希望将类用作bean,则可能需要一个可工作的setter,这至少看起来是可行的。

实际上,我的问题是关于实体的equals和hashcode。遗留代码会带来很多问题,永远不要忘记检查它。我所做的只是保持删除孤立策略和正确的等号和hashcode。

当我在我的父实体中使用这些注释时,我面临着类似的问题:

@Cascade({ CascadeType.ALL, CascadeType.DELETE_ORPHAN })

错误地,我试图在数据库中保存一个空父对象,并正确设置我的实体对象的值解决了我的错误。所以,做检查,如果你是愚蠢的设置错误的值或试图在数据库中保存一个空对象。