我已经离开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,无论它们是否是孤立删除的结果。
答案 0 :(得分:2)
事实证明,需要配置OpenJPA以便它知道数据库中现有的外键约束,否则它可能会在删除子节点之前尝试删除父节点。解决方案是将此行添加到persistence.xml:
<property name="openjpa.jdbc.SchemaFactory" value="native(ForeignKeys=true)" />