Java OpenJPA:级联删除引发PersistenceException

Java OpenJPA:级联删除引发PersistenceException,java,jpa-2.0,openjpa,Java,Jpa 2.0,Openjpa,我已经离开Java世界有一段时间了,我对JPA是新手。我有一个数据模型,风力涡轮机可以有几个性能曲线,而这些性能曲线又包含几个性能曲线点。我已经在关系上设置了cascade=CascadeType.ALL和orphanRemoving=true 当我从WindTurbine中删除PerformanceCurve时,我会得到一个PersistenceException,因为数据库中有引用PerformanceCurve的PerfCurvePoint记录 我希望PerfCurvePoint记录将与孤

我已经离开Java世界有一段时间了,我对JPA是新手。我有一个数据模型,风力涡轮机可以有几个性能曲线,而这些性能曲线又包含几个性能曲线点。我已经在关系上设置了cascade=CascadeType.ALL和orphanRemoving=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);
    }
}
@实体
公共类WindTurbine实现可序列化{
@OneToMany(mappedBy=“turbine”,fetch=FetchType.EAGER,cascade=CascadeType.ALL,orphan=true)
私有ArrayList perfCurves=新ArrayList();
...
}
@实体
公共类PerformanceCurve实现可序列化{
@多通(可选=假)
@JoinColumn(name=“TURBINE\u ID”,referencedColumnName=“TURBINE\u ID”)
私人风力涡轮机;
@OneToMany(mappedBy(“perfCurve”,fetch=FetchType.EAGER,cascade=CascadeType.ALL,orphan=true)
private ArrayList points=new ArrayList();
...
}
@实体
公共类PerfCurvePoint实现可序列化{
@多通(可选=假)
@JoinColumn(name=“PERF\u CURVE\u ID”,referencedColumnName=“PERF\u CURVE\u ID”)
私人绩效曲线;
...
}
公开课Foo{
公共空栏(风力涡轮机){
//下一行导致引发PersistenceException
//在刷新/提交时,如果性能曲线包含任何点。
涡轮机。getPerformanceCurves()。移除(1);
}
公共无效工作区(EntityManager em、风力涡轮机){
//这是可行的,但需要调用
//我希望避免的EntityManager.flush()。
PerformanceCurve曲线=turbine.getPerformanceCurves().get(1);
curve.getPoints().clear();
em.flush();
turbine.getPerformanceCurves().删除(曲线);
}
}

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

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

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


它应该可以工作。您的jpa实现是什么。作为修复程序,您不需要清除收集并在EM上调用flush,EM.remove(PerformanceCurve)应该足够了。不过cascade.all with Oliver Removing应该可以完成这项工作。谢谢Zielu,这帮助我走上了正确的道路。事实证明,我的级联删除都不起作用。我们使用的是OpenJPA 2.2.3,我没有将其设置为考虑数据库的外键。我已经编辑了这个问题,并将发布解决方案以防其他人无意中发现。