OpenJPA:级联删除抛出 PersistenceException

OpenJPA: Cascading delete throws PersistenceException

离开Java世界有一段时间了,我是JPA新手。我有一个数据模型,其中 WindTurbines 可以有多个 PerformanceCurves,而这些 PerformanceCurves 又将包含多个 PerfCurvePoints。我在关系上设置了 cascade=CascadeType.ALL 和 orphanRemoval=true。

当我从 WindTurbine 中删除 PerformanceCurve 时,出现 PersistenceException,因为数据库中有引用 PerformanceCurve 的 PerfCurvePoint 记录。

我预计 PerfCurvePoint 记录会与孤立​​的 PerformanceCurve 一起自动删除,因为我在该关系上指定了 CascadeType.ALL。

我知道我可以通过清除 PerformanceCurve 对象上的 PerfCurvePoints 集合并在从 WindTurbine 中删除 PerformanceCurve 之前调用 EntityManager.flush() 来解决这个问题,但我不喜欢在中引用 EntityManager我们应用程序的那一层。有没有更好的方法来处理这个问题?

@Entity
public class WindTurbine implements Serializable {

    @OneToMany(mappedBy="turbine", fetch=FetchType.EAGER, cascade=CascadeType.ALL, orphanRemoval=true)
    private ArrayList<PerformanceCurve> perfCurves = new ArrayList<>();

    ...

}


@Entity
public class PerformanceCurve implements Serializable {

    @ManyToOne(optional=false)
    @JoinColumn(name="TURBINE_ID", referncedColumnName="TURBINE_ID")
    private WindTurbine turbine;

    @OneToMany(mappedBy("perfCurve", fetch=FetchType.EAGER, cascade=CascadeType.ALL, orphanRemoval=true)
    private ArrayList<PerfCurvePoint> points = new ArrayList<>();

    ...

}

@Entity
public class PerfCurvePoint implements Serializable {

    @ManyToOne(optional=false)
    @JoinColumn(name="PERF_CURVE_ID", referncedColumnName="PERF_CURVE_ID")
    private PerformanceCurve perfCurve;

    ...

}

public class Foo {

    public void Bar(WindTurbine turbine) {
        // The following line causes a PersistenceException to be thrown
        //   on flush/commit if the performance curve contains any points.
        turbine.getPerformanceCurves().remove(1);
    }

    public void Workaround(EntityManager em, WindTurbine turbine) {
        // This works, but it requires a call to 
        //   EntityManager.flush() that I would like to avoid.
        PerformanceCurve curve = turbine.getPerformanceCurves().get(1);
        curve.getPoints().clear();
        em.flush();
        turbine.getPerformanceCurves().remove(curve);
    }
}

编辑:我实际上在所有级联删除上都遇到了 PersistenceException,无论它们是否是孤立删除的结果。

事实证明,OpenJPA 需要进行配置,以便它知道数据库中现有的外键约束,否则它可能会在删除子项之前尝试删除父项。解决方案是将此行添加到 persistence.xml:

<property name="openjpa.jdbc.SchemaFactory" value="native(ForeignKeys=true)" />