Java OpenJPA:级联删除引发PersistenceException
我已经离开Java世界有一段时间了,我对JPA是新手。我有一个数据模型,风力涡轮机可以有几个性能曲线,而这些性能曲线又包含几个性能曲线点。我已经在关系上设置了cascade=CascadeType.ALL和orphanRemoving=true 当我从WindTurbine中删除PerformanceCurve时,我会得到一个PersistenceException,因为数据库中有引用PerformanceCurve的PerfCurvePoint记录 我希望PerfCurvePoint记录将与孤立的PerformanceCurve一起自动删除,因为我在该关系上指定了CascadeType.ALL 我知道我可以通过清除PerformanceCurve对象上的PerfCurvePoints集合并在从WindTurbine中删除PerformanceCurve之前调用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记录将与孤
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,我没有将其设置为考虑数据库的外键。我已经编辑了这个问题,并将发布解决方案以防其他人无意中发现。