JPA 2.1:使用 orphanRemoval 收到 org.hibernate.exception.ConstraintViolationException
JPA 2.1: received org.hibernate.exception.ConstraintViolationException using orphanRemoval
我有 3 个具有以下映射的实体,我想在删除父实体时使用 orphanRemoval:
@Entity
@Table(name = "EvaluationRequest", schema = "dbo")
public class EvaluationRequestDMO implements java.io.Serializable {
private Set<EvalStatusDMO> evaluationStatuses = new HashSet<EvalStatusDMO>(0);
@OneToMany(fetch = FetchType.LAZY, mappedBy = "evaluationRequest", orphanRemoval = true)
public Set<EvalStatusDMO> getEvaluationStatuses() {
return this.evaluationStatuses;
}
}
@Entity
@Table(name = "EvaluationStatus")
public class EvalStatusDMO implements Serializable{
private EvaluationRequestDMO evaluationRequest;
private EvaluationResponseDMO evaluationResponce;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "EvalRequestId", nullable = false)
public EvaluationRequestDMO getEvaluationRequest() {
return evaluationRequest;
}
public void setEvaluationRequest(EvaluationRequestDMO evaluationRequestDMO) {
this.evaluationRequest = evaluationRequestDMO;
}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "EvalResponseId", nullable = false)
public EvaluationResponseDMO getEvaluationResponce() {
return evaluationResponce;
}
public void setEvaluationResponce(EvaluationResponseDMO evaluationResponceDMO) {
this.evaluationResponce = evaluationResponceDMO;
}
}
@Entity
@Table(name = "EvaluationResponse")
public class EvaluationResponseDMO implements Serializable{
private Set<EvalStatusDMO> evalStatusDMO = new HashSet<EvalStatusDMO>(0);
@OneToMany(fetch = FetchType.LAZY, mappedBy = "evaluationResponce", orphanRemoval = true)
public Set<EvalStatusDMO> getEvalStatusDMO() {
return evalStatusDMO;
}
}
现在我想删除 EvaluationRequest
和 EvaluationResponse
个实体:
@Override
@Transactional
public void deleteEvaluationInfoByPgSelIdAndProfileId(long programSelectedId, long profileId) {
List<EvaluationRequestDMO> evaluationRequestDMOList = evaluationRequestDAO.findByProfileIdAndProgramId(profileId, programSelectedId);
if (evaluationRequestDMOList != null) {
List<EvaluationResponseDMO> evaluationResponseDMOList = new ArrayList<>();
for (EvaluationRequestDMO evaluationRequestDMO : evaluationRequestDMOList) {
if (evaluationRequestDMO.getEvaluationStatuses() != null) {
evaluationResponseDMOList.addAll(collect(evaluationRequestDMO.getEvaluationStatuses(), TransformerUtils.invokerTransformer("getEvaluationResponce")));
}
}
filter(evaluationRequestDMOList, PredicateUtils.notNullPredicate());
evaluationResponseDAO.deleteInBatch(evaluationResponseDMOList);
evaluationRequestDAO.deleteInBatch(evaluationRequestDMOList);
}
}
删除 evaluationResponseDAO.deleteInBatch(evaluationResponseDMOList);
我得到 org.hibernate.exception.ConstraintViolationException
:
The DELETE statement conflicted with the REFERENCE constraint "FK_EvaluationStatus_EvaluationResponse". The conflict occurred in database "unicas_ux", table "dbo.EvaluationStatus", column 'EvalResponseId'
.
我知道按以下顺序删除成功:
EvaluationStatusDMO->EvaluationResponceDMO->EvaluationRequestDMO
但是,我该如何使用 orphanRemoval 来完成它?
你删除的顺序是先request再response吧?我们来看一下。
请求
- 与状态 orphanRemoval=true
有关系
回应
- 也与状态有关,orphanRemoval=true
状态
- 与请求的关系 --> nullable=false
- 与响应的关系 --> nullable= false
问题:
如果删除请求,则您将实体配置为也删除其状态实体。但此时状态也与仍然存在的响应有关系并对其有参考。
这行不通。您必须先解决所有状态关系,然后才能删除它。
我想出了解决问题的方法。我的子实体 EvalStatusDMO
与 EvaluationResponseDMO
和 EvaluationRequestDMO
都有关系。要正确删除所有内容,我必须清除其中一个关系中的 EvalStatusDMO
集(见下文)。
@Override
@Transactional
public void deleteEvaluationInfoByPgSelIdAndProfileId(long programSelectedId, long profileId) {
List<EvaluationRequestDMO> evaluationRequestDMOList = evaluationRequestDAO.findByProfileIdAndProgramId(profileId, programSelectedId);
if (evaluationRequestDMOList != null) {
List<EvaluationResponseDMO> evaluationResponseDMOList = new ArrayList<>();
for (EvaluationRequestDMO evaluationRequestDMO : evaluationRequestDMOList) {
if (evaluationRequestDMO.getEvaluationStatuses() != null) {
evaluationResponseDMOList.addAll(collect(evaluationRequestDMO.getEvaluationStatuses(), TransformerUtils.invokerTransformer("getEvaluationResponce")));
evaluationRequestDMO.getEvaluationStatuses().clear();
}
}
filter(evaluationRequestDMOList, PredicateUtils.notNullPredicate());
evaluationRequestDAO.deleteInBatch(evaluationRequestDMOList);
evaluationResponseDAO.deleteInBatch(evaluationResponseDMOList);
}
}
所以逻辑如下:
- 对于每个
EvaluationRequestDMO
我应该清除 EvalStatusDMO
。
- 删除所有 'EvaluationRequestDMO'。
- 删除所有 'EvaluationResponseDMO'。
- 所有
EvalStatusDMO
将被自动删除,因为 orphanRemoval=true
我有 3 个具有以下映射的实体,我想在删除父实体时使用 orphanRemoval:
@Entity
@Table(name = "EvaluationRequest", schema = "dbo")
public class EvaluationRequestDMO implements java.io.Serializable {
private Set<EvalStatusDMO> evaluationStatuses = new HashSet<EvalStatusDMO>(0);
@OneToMany(fetch = FetchType.LAZY, mappedBy = "evaluationRequest", orphanRemoval = true)
public Set<EvalStatusDMO> getEvaluationStatuses() {
return this.evaluationStatuses;
}
}
@Entity
@Table(name = "EvaluationStatus")
public class EvalStatusDMO implements Serializable{
private EvaluationRequestDMO evaluationRequest;
private EvaluationResponseDMO evaluationResponce;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "EvalRequestId", nullable = false)
public EvaluationRequestDMO getEvaluationRequest() {
return evaluationRequest;
}
public void setEvaluationRequest(EvaluationRequestDMO evaluationRequestDMO) {
this.evaluationRequest = evaluationRequestDMO;
}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "EvalResponseId", nullable = false)
public EvaluationResponseDMO getEvaluationResponce() {
return evaluationResponce;
}
public void setEvaluationResponce(EvaluationResponseDMO evaluationResponceDMO) {
this.evaluationResponce = evaluationResponceDMO;
}
}
@Entity
@Table(name = "EvaluationResponse")
public class EvaluationResponseDMO implements Serializable{
private Set<EvalStatusDMO> evalStatusDMO = new HashSet<EvalStatusDMO>(0);
@OneToMany(fetch = FetchType.LAZY, mappedBy = "evaluationResponce", orphanRemoval = true)
public Set<EvalStatusDMO> getEvalStatusDMO() {
return evalStatusDMO;
}
}
现在我想删除 EvaluationRequest
和 EvaluationResponse
个实体:
@Override
@Transactional
public void deleteEvaluationInfoByPgSelIdAndProfileId(long programSelectedId, long profileId) {
List<EvaluationRequestDMO> evaluationRequestDMOList = evaluationRequestDAO.findByProfileIdAndProgramId(profileId, programSelectedId);
if (evaluationRequestDMOList != null) {
List<EvaluationResponseDMO> evaluationResponseDMOList = new ArrayList<>();
for (EvaluationRequestDMO evaluationRequestDMO : evaluationRequestDMOList) {
if (evaluationRequestDMO.getEvaluationStatuses() != null) {
evaluationResponseDMOList.addAll(collect(evaluationRequestDMO.getEvaluationStatuses(), TransformerUtils.invokerTransformer("getEvaluationResponce")));
}
}
filter(evaluationRequestDMOList, PredicateUtils.notNullPredicate());
evaluationResponseDAO.deleteInBatch(evaluationResponseDMOList);
evaluationRequestDAO.deleteInBatch(evaluationRequestDMOList);
}
}
删除 evaluationResponseDAO.deleteInBatch(evaluationResponseDMOList);
我得到 org.hibernate.exception.ConstraintViolationException
:
The DELETE statement conflicted with the REFERENCE constraint "FK_EvaluationStatus_EvaluationResponse". The conflict occurred in database "unicas_ux", table "dbo.EvaluationStatus", column 'EvalResponseId'
.
我知道按以下顺序删除成功:
EvaluationStatusDMO->EvaluationResponceDMO->EvaluationRequestDMO
但是,我该如何使用 orphanRemoval 来完成它?
你删除的顺序是先request再response吧?我们来看一下。
请求
- 与状态 orphanRemoval=true 有关系
回应
- 也与状态有关,orphanRemoval=true
状态
- 与请求的关系 --> nullable=false
- 与响应的关系 --> nullable= false
问题: 如果删除请求,则您将实体配置为也删除其状态实体。但此时状态也与仍然存在的响应有关系并对其有参考。
这行不通。您必须先解决所有状态关系,然后才能删除它。
我想出了解决问题的方法。我的子实体 EvalStatusDMO
与 EvaluationResponseDMO
和 EvaluationRequestDMO
都有关系。要正确删除所有内容,我必须清除其中一个关系中的 EvalStatusDMO
集(见下文)。
@Override
@Transactional
public void deleteEvaluationInfoByPgSelIdAndProfileId(long programSelectedId, long profileId) {
List<EvaluationRequestDMO> evaluationRequestDMOList = evaluationRequestDAO.findByProfileIdAndProgramId(profileId, programSelectedId);
if (evaluationRequestDMOList != null) {
List<EvaluationResponseDMO> evaluationResponseDMOList = new ArrayList<>();
for (EvaluationRequestDMO evaluationRequestDMO : evaluationRequestDMOList) {
if (evaluationRequestDMO.getEvaluationStatuses() != null) {
evaluationResponseDMOList.addAll(collect(evaluationRequestDMO.getEvaluationStatuses(), TransformerUtils.invokerTransformer("getEvaluationResponce")));
evaluationRequestDMO.getEvaluationStatuses().clear();
}
}
filter(evaluationRequestDMOList, PredicateUtils.notNullPredicate());
evaluationRequestDAO.deleteInBatch(evaluationRequestDMOList);
evaluationResponseDAO.deleteInBatch(evaluationResponseDMOList);
}
}
所以逻辑如下:
- 对于每个
EvaluationRequestDMO
我应该清除EvalStatusDMO
。 - 删除所有 'EvaluationRequestDMO'。
- 删除所有 'EvaluationResponseDMO'。
- 所有
EvalStatusDMO
将被自动删除,因为orphanRemoval=true