2012-01-26 41 views
2

我有两个独立的实体类:Job和JobOrgUnitCfg 下面我把两段代码做成同样的选择对象。where语句的区别beetwen JPQL和CriteriaBuilder

在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

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

它应该在EclipseLink的最新版本或构建中修复。

+0

谢谢。我检查了最新发布的eclipselink 2.3.0版,但尚未修复。 –