我有以下问题时,试图更新我的实体:
"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<..只有>,根据这个:如何“可能”解决问题,但它没有工作。
如果你有什么想法,请告诉我。
谢谢!
所有这些答案都帮不了我,但我找到了另一个解决办法。
我有一个实体A包含一个实体B的列表实体B包含一个实体C的列表。
我试图更新实体A和b,它成功了。但是当更新实体C时,我得到了上述错误。在实体B中,我有一个这样的注释:
@OneToMany(mappedBy = "entity_b", cascade = [CascadeType.ALL] , orphanRemoval = true)
var c: List<EntityC>?,
我只是删除了orphanRemoval和更新工作。
在我的例子中,它是从几个线程并发访问一个Hibernate会话。
我有Spring Boot Batch和RepositoryItemReader实现,其中我通过大小为10的页面请求获取实体。
例如,我的实体是:
@Entity
class JobEntity {
@ManyToOne(fetch = FetchType.LAZY)
private GroupEntity group;
}
@Entity
class GroupEntity {
@OneToMany(mappedBy = "group", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
private Set<Config> configs;
}
批处理:在一个事务中读取器->处理器->写入器。
在该实体配置中,GroupEntity可以转义到其他线程:
进入read部分的第一个线程获取大小为10的JobEntity页面(RepositoryItemReader#doRead),该项目包含一个共享的GroupEntity对象(因为它们都指向相同的组id)。然后取第一个实体。接下来读取部分的线程一个接一个地从该页中取出JobEntity,直到耗尽该页。
所以现在线程可以访问与JobEntity实例相同的GroupEntity实例,这是不安全的多线程访问一个Hibernate会话。
我在尝试使用TreeSet时遇到了这个问题。我用TreeSet初始化了oneToMany
@OneToMany(mappedBy = "question", fetch = FetchType.EAGER, cascade = { CascadeType.ALL }, orphanRemoval=true)
@OrderBy("id")
private Set<WizardAnswer> answers = new TreeSet<WizardAnswer>();
但是,这将带来上述问题中所描述的错误。看起来hibernate支持SortedSet如果你把上面的行改成
@OneToMany(mappedBy = "question", fetch = FetchType.EAGER, cascade = { CascadeType.ALL }, orphanRemoval=true)
@OrderBy("id")
private SortedSet<WizardAnswer> answers;
它像魔法一样起作用:)
更多关于hibernate SortedSet的信息可以在这里