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;
    }

}

现在我想删除 EvaluationRequestEvaluationResponse 个实体:

@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

问题: 如果删除请求,则您将实体配置为也删除其状态实体。但此时状态也与仍然存在的响应有关系并对其有参考。

这行不通。您必须先解决所有状态关系,然后才能删除它。

我想出了解决问题的方法。我的子实体 EvalStatusDMOEvaluationResponseDMOEvaluationRequestDMO 都有关系。要正确删除所有内容,我必须清除其中一个关系中的 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);
    }
}

所以逻辑如下:

  1. 对于每个 EvaluationRequestDMO 我应该清除 EvalStatusDMO
  2. 删除所有 'EvaluationRequestDMO'。
  3. 删除所有 'EvaluationResponseDMO'。
  4. 所有 EvalStatusDMO 将被自动删除,因为 orphanRemoval=true