我有一个Contract
和Phase
。
Contract
存储Phase
的列表。
Phase
被实现为层次结构:具有父Phase
和子列表Phase
。
映射代码为:
public class Contract {
@OneToMany(mappedBy = "contract", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Phase> phases;
}
public class Phase {
private String display_no;
@ManyToOne
@JoinColumn(name = "contract_no", referencedColumnName = "contract_no", insertable = false, updatable = false)
private Contract contract;
@ManyToOne
@JoinColumns({
@JoinColumn(name = "contract_no", referencedColumnName = "contract_no", insertable = false, updatable = false),
@JoinColumn(name = "parent_phase_no", referencedColumnName = "phase_no", insertable = false, updatable = false) })
private Phase parentPhase;
@OneToMany(mappedBy = "parentPhase", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Phase> subPhases;
}
假设我有Contract
个CTR1及其Phase
(phase_no | display_no):
然后,我要删除Phase
1.1及其子级。我有一个名为selectedPhses
的变量,包含将按照子对父顺序删除的阶段:[1.1.2
,1.1.1
,1.1
](因为我认为一个阶段可以是仅在删除其子级后删除)
// selectedPhses = [1.1.2 , 1.1.1 , 1.1]
for (Phase phs : selectedPhses) {
Phase parent = phs.getParentPhase();
// delete phase from parent
if (parent != null) {
parent.getSubPhases().remove(phs);
}
// delete phase from contract
contract.getPhases().remove(phs);
// entityManager.flush();
}
正如我从上述代码中所期望的那样,将首先删除1.1.2
,然后删除1.1.1
,最后删除1.1
。我还在@PreRemove
创建了一个侦听器,以查看删除顺序。正确(4-> 3-> 2):
DEBUG [2019-06-16 22:20:42,555] th.entity.Phase(preRemove:529) - Removing th.entity.Phase[PK: (contract_no=CTR1;phase_no=4;)];
DEBUG [2019-06-16 22:20:42,555] th.entity.Phase(preRemove:529) - Removing th.entity.Phase[PK: (contract_no=CTR1;phase_no=3;)];
DEBUG [2019-06-16 22:20:42,556] th.entity.Phase(preRemove:529) - Removing th.entity.Phase[PK: (contract_no=CTR1;phase_no=2;)];
但是当jpa执行DELETE查询时,其顺序与上面的日志不同(2-> 4-> 3):
executing prepstmnt 661533276 DELETE FROM Phase WHERE contract_no= ? AND phase_no= ? [params=(String) CTR1, (int) 2]
executing prepstmnt 661533276 DELETE FROM Phase WHERE contract_no= ? AND phase_no= ? [params=(String) CTR1, (int) 4]
executing prepstmnt 661533276 DELETE FROM Phase WHERE contract_no= ? AND phase_no= ? [params=(String) CTR1, (int) 3]
执行顺序违反db约束并引发Exception。我通过在for循环(注释行)的末尾添加flush()
进行了测试,并且可以正常工作。但是很多人不推荐flush()
,所以我不会使用它。
问题是:
谢谢!