JPQL和CriteriaBuilder中where子句的差异

3
我可以帮你翻译成中文。以下是需要翻译的内容:

我有两个单独的实体类:Job和JobOrgUnitCfg 下面是两个代码片段,使它们在这些对象上执行相同的选择。

在JPQL中的第一个查询:

    Query jobOrgUnitCfgQuery = entityManager.createQuery(
            "SELECT c FROM JobOrgUnitCfg c WHERE c.orgId = :orgId and c.schedulerNextActivation < current_timestamp and c.active = :active and " +
            " not exists (SELECT j  FROM Job j WHERE j.orderId = c.orderId and j.orgId = c.orgId and j.status <> :jobStatus)");

    jobOrgUnitCfgQuery.setParameter("orgId", orgId);
    jobOrgUnitCfgQuery.setParameter("jobStatus", JobStatusEnum.End);
    jobOrgUnitCfgQuery.setParameter("active", Boolean.TRUE);
    return jobOrgUnitCfgQuery.getResultList();

第二个查询使用CriteriaBuilder构建:

    CriteriaBuilder cb = entityManager.getCriteriaBuilder();
    CriteriaQuery<JobOrgUnitCfg> criteria = cb.createQuery(JobOrgUnitCfg.class);
    Root<JobOrgUnitCfg> jobOrgUnitCfgRoot = criteria.from(JobOrgUnitCfg.class);

    Subquery<Job> subquery = criteria.subquery(Job.class);
    Root<Job> jobRoot = subquery.from(Job.class);

    subquery.where(
            cb.and(
                    cb.equal(jobRoot.get(Job_.orderId), jobOrgUnitCfgRoot.get(JobOrgUnitCfg_.orderId)),
                    cb.equal(jobRoot.get(Job_.orgId), jobOrgUnitCfgRoot.get(JobOrgUnitCfg_.orgId)),
                    cb.not(cb.equal(jobRoot.get(Job_.status), JobStatusEnum.End))
            )
    );

    Predicate where = cb.and(cb.equal(jobOrgUnitCfgRoot.get(JobOrgUnitCfg_.orgId), orgId),
            cb.lessThan(jobOrgUnitCfgRoot.get(JobOrgUnitCfg_.schedulerNextActivation), cb.currentTimestamp()),
            cb.equal(jobOrgUnitCfgRoot.get(JobOrgUnitCfg_.active), Boolean.TRUE),
            cb.not(cb.exists(subquery))
    );

    criteria.where(where);
    TypedQuery<JobOrgUnitCfg> query = entityManager.createQuery(criteria);
    return query.getResultList();

首先生成错误的where子句(在子查询中重复使用表S_JOBS_ORG_UNIT_CFG):

SELECT ... FROM S_JOBS_ORG_UNIT_CFG t0 
WHERE ((((t0.ORG_ID = ?) AND (t0.SCHEDULER_NEXT_ACTIVATION < SYSDATE)) AND (t0.ACTIVE = ?)) 
AND NOT EXISTS (SELECT ? FROM S_JOBS_ORG_UNIT_CFG t2, S_JOBS t1 WHERE ((((t1.ORDER_ID = t2.ORDER_ID) AND (t1.ORG_ID = t2.ORG_ID)) AND (t1.STATUS <> ?)) AND (t0.ORDER_ID = t2.ORDER_ID))) )

Criteriabuilder生成的SQL语句是正确的:

SELECT ... FROM S_JOBS_ORG_UNIT_CFG t0 
WHERE ((((t0.ORG_ID = ?) AND (t0.SCHEDULER_NEXT_ACTIVATION < SYSDATE)) AND (t0.ACTIVE = ?)) 
AND NOT EXISTS (SELECT ? FROM S_JOBS t1 WHERE (((t1.ORDER_ID = t0.ORDER_ID) AND (t1.ORG_ID = t0.ORG_ID)) AND NOT ((t1.STATUS = ?)))) )

有人可以解释一下我的JPQL有什么问题吗?
1个回答

1

我认为这只是JPQL中的一个错误,添加了额外的表连接。它不应该影响结果。

在最新版本或EclipseLink的构建中应该已经修复了这个问题。


谢谢。我已经检查了最新发布的EclipseLink版本2.3.0,但问题仍未得到解决。 - Dariusz Skrudlik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接