当实体之间的关系不直接时,我会遇到Cascade Persist和Cascade Remove(+孤立删除)的问题。 数据模型很复杂,因此我尝试将其精炼为基本模型。我的“系统”有几个具有相同超类的输入和输出
@Entity(...)
public class System {
@OneToMany(mappedBy = "system",
cascade = CascadeType.ALL,
fetch = FetchType.LAZY,
orphanRemoval=true)
@MapKey(name = "index")
Map<Integer,InLocator> inputs
@OneToMany(mappedBy = "system",
cascade = CascadeType.ALL,
fetch = FetchType.LAZY,
orphanRemoval=true)
@MapKey(name = "index")
Map<Integer,OutLocator> outputs;
}
这些是SystemLocators的几种类型
@Entity(...)
public class InLocator extends SystemLocator {
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name = "system_in")
protected System system;
protected int index;
}
@Entity(...)
public class OutLocator extends SystemLocator {
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name = "system_out")
protected Systen system;
protected int index;
}
现在出现了问题:基类与其自身类型的inputSource有关系。
@Entity(...)
public abstract class SystemLocator {
@ManyToOne(fetch=FetchType.LAZY)
protected SystemLocator inputSource;
}
其背后的想法是:一个系统的输出将用作另一个系统的输入的源。并且系统(在最简单的情况下)可能会将其中一个输入作为其中一个输出的源。
现在我注意到,当我用Cascade.PERSIST注释此inputSource关系时,然后在删除某些内容时会遇到麻烦
system.inputs.remove(x);
system.outputs.remove(x);
因为我最终遇到这样的情况,我有一个由Cascade.PERSIST和cascade.REMOVE关系引用的SystemLocator实例,并且不会被(无提示地)删除。
另一方面:当我不使用Cascade.PERSIST注释inputSource关系时,则很难持久化域模型:
systemA.outputs.put(i, new OutLocator(i,...));
systemB.inputs.put(i, new InLocator(i,...));
systemB.inputs.get(i).setInputSource(systemA.outputs.get(i));
将导致错误消息“对象引用了未保存的瞬态实例-在刷新之前保存瞬态实例:OutLocator.input-> SystemLocator”
我理解它的方式(如果我错了,请纠正我):在刷新时,Hibernate将遍历这些关系,并在级联.PERSIST的情况下向实体添加持久性上下文。而且我相信我的问题是在以下情况下发生的:Hibernate具有不同的遍历关系的路径,并选择了应首先遍历的关系。
我知道正确位置的flush()可以解决我的问题。但是这些方法在我无法访问EntityManager的域mobel中。
遇到相同问题并且知道一个好的解决方案的人?