休眠级联持久/删除及其完成顺序

时间:2018-08-12 12:41:35

标签: java hibernate jpa hibernate-cascade

当实体之间的关系不直接时,我会遇到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中。

遇到相同问题并且知道一个好的解决方案的人?

0 个答案:

没有答案