JPA 2.1:使用orphanRemoval收到org.hibernate.exception.ConstraintViolationException

时间:2017-02-22 13:52:13

标签: hibernate jpa jpa-2.0 jpa-2.1

我有3个具有以下映射的enties,当我想删除父实体时,我想使用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-&GT; EvaluationResponceDMO-&GT; EvaluationRequestDMO

但是,我怎么能用orphanRemoval来做呢?

2 个答案:

答案 0 :(得分:0)

您要删除的订单是请求,然后是响应,对吗?我们来看一下。

请求

  • 与状态orphanRemoval = true
  • 有关系

<强>响应

  • 还与状态有关系,orphanRemoval = true

状态

  • 与请求的关系 - &gt;可空=假
  • 与回应的关系 - &gt; nullable = false

问题: 如果删除请求,则会将实体配置为同时删除其状态实体。但此时此状态还与仍然存在的响应有关,并且可以参考它。

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

答案 1 :(得分:0)

我已经弄清楚如何解决这个问题。我的子实体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);
    }
}

所以逻辑将遵循:

    每个EvaluationRequestDMO
  1. 我应该清除EvalStatusDMO
  2. 删除所有&#39; EvaluationRequestDMO&#39;。
  3. 删除所有&#39; EvaluationResponseDMO&#39;。
  4. 由于EvalStatusDMO
  5. ,所有orphanRemoval=true都会自动删除