JPA 2 Criteria API - 使用Eclipselink将JPQL转换为Criteria API查询的异常

时间:2010-12-20 12:51:21

标签: eclipselink jpa-2.0 criteria-api

我在将JPA查询转换为使用Criteria API

时遇到问题

我有以下查询尝试查找与传递的地址参数匹配的ServiceUser。 ServiceUser是一个抽象实体,具有子类和成人的具体子类。我正在使用ServiceUser类上的联接继承策略。

当我称这种方法时,一切正常。

public Set<T> findByAddress(Address address) {

    Query query = manager.createQuery("SELECT distinct s FROM ServiceUser AS s JOIN s.addressHistory as h where h = :address");
    query.setParameter("address", address);

    HashSet<T> result = new HashSet<T>();
    for (Object s : query.getResultList()) {
        // tClass is the runtime type of the generic session bean.
        if (this.tClass.isInstance(s)) {
            result.add((T) s);
        }
    }

     return result;
}

但是,如果我尝试用以下使用生成的元模型和typedquery替换该函数,那么我将得到一个异常

public Set<T> findByAddress(Address address) {

    CriteriaBuilder cb = manager.getCriteriaBuilder();
    CriteriaQuery<ServiceUser> cq = cb.createQuery(ServiceUser.class);
    Root<ServiceUser> su = cq.from(ServiceUser.class);

    Join<ServiceUser, Address> addressHistory = su.join(ServiceUser_.addressHistory);
    cq.select(su).distinct(true).where(cb.equal(addressHistory, cb.parameter(Address.class, "address")));
    TypedQuery<ServiceUser> q = manager.createQuery(cq);
    q.setParameter("address", address);

    HashSet<T> result = new HashSet<T>();
    for (ServiceUser s : q.getResultList()) {
        // tClass is the runtime type of the generic session bean.
        if (this.tClass.isInstance(s)) {
            result.add((T) s);
        }
    }

    return result;
}

这是堆栈跟踪将Eclipslink日志记录。似乎有抛出NulPointerException,但我不确定为什么?

 /**
Test : shouldBeAbleToFindChildByAddress()
uk.gov.sunderland.ccms.model.bean.ChildService.findByAddress(Address[id=1,lineOne=7,lineTwo=Camberwell Way,lineThree=Moorside,lineFour=Sunderland,postcode=SR7 3XN])
[EL Finer]: 2010-12-20 12:39:42.89--ServerSession(7055953)--Thread(Thread[pool-52-thread-1,5,grizzly-kernel])--client acquired
[EL Finer]: 2010-12-20 12:39:42.89--UnitOfWork(22763294)--Thread(Thread[pool-52-thread-1,5,grizzly-kernel])--TX binding to tx mgr, status=STATUS_ACTIVE
[EL Finest]: 2010-12-20 12:39:42.89--UnitOfWork(22763294)--Thread(Thread[pool-52-thread-1,5,grizzly-kernel])--Execute query ReadObjectQuery(referenceClass=Address sql="SELECT ID, LINE_TWO, LINE_THREE, LINE_ONE, LINE_FOUR, POSTCODE FROM ADDRESS WHERE (ID = ?)")
[EL Finest]: 2010-12-20 12:39:42.906--UnitOfWork(22763294)--Thread(Thread[pool-52-thread-1,5,grizzly-kernel])--Execute query ReadAllQuery(referenceClass=ServiceUser )
[EL Finest]: 2010-12-20 12:39:42.906--ServerSession(7055953)--Thread(Thread[pool-52-thread-1,5,grizzly-kernel])--reconnecting to external connection pool
[EL Fine]: 2010-12-20 12:39:42.906--ServerSession(7055953)--Connection(32184426)--Thread(Thread[pool-52-thread-1,5,grizzly-kernel])--SELECT DISTINCT t2.SERVICE_USER_TYPE FROM ADDRESS t0, SERVICE_USER t2, SERVICE_USER_ADDRESS t1 WHERE ((? = t0.ID) AND ((t1.SERVICE_USER_ID = t2.ID) AND (t0.ID = t1.ADDRESS_ID)))
        bind => [1]
[EL Finer]: 2010-12-20 12:39:42.906--UnitOfWork(22763294)--Thread(Thread[pool-52-thread-1,5,grizzly-kernel])--class uk.gov.sunderland.ccms.model.entity.Adult
[EL Finest]: 2010-12-20 12:39:42.906--ServerSession(7055953)--Thread(Thread[pool-52-thread-1,5,grizzly-kernel])--reconnecting to external connection pool
[EL Fine]: 2010-12-20 12:39:42.906--ServerSession(7055953)--Connection(29495316)--Thread(Thread[pool-52-thread-1,5,grizzly-kernel])--SELECT DISTINCT t0.ID, t0.SERVICE_USER_TYPE, t0.TITLE, t0.DOB, t0.GENDER, t0.DISABILITY, t0.ETHNICITY, t1.ID, t1.EMPLOYMENT, t1.INFO_PACK_REQUIRED, t1.HOME_PHONE, t1.OTHER_LANGUAGE, t1.REFERRER, t1.MOBILE_PHONE, t1.LONE_PARENT, t1.GP_PRACTICE, t1.CONTACTABLE, t1.WORK_PHONE, t1.BABY_DUE_DATE, t1.ENGLISH_LEVEL FROM SERVICE_USER_ADDRESS t3, ADDRESS t2, ADULT t1, SERVICE_USER t0 WHERE (((? = t2.ID) AND ((t1.ID = t0.ID) AND (t0.SERVICE_USER_TYPE = ?))) AND ((t3.SERVICE_USER_ID = t0.ID) AND (t2.ID = t3.ADDRESS_ID)))
        bind => [1, 1]
[EL Warning]: 2010-12-20 12:39:42.906--UnitOfWork(22763294)--Thread(Thread[pool-52-thread-1,5,grizzly-kernel])--java.lang.NullPointerException
        at org.eclipse.persistence.descriptors.InheritancePolicy.selectAllRowUsingDefaultMultipleTableSubclassRead(InheritancePolicy.java:1355)
        at org.eclipse.persistence.descriptors.InheritancePolicy.selectAllRowUsingMultipleTableSubclassRead(InheritancePolicy.java:1396)
        at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.selectAllRows(ExpressionQueryMechanism.java:2493)
        at org.eclipse.persistence.queries.ReadAllQuery.executeObjectLevelReadQuery(ReadAllQuery.java:407)
        at org.eclipse.persistence.queries.ObjectLevelReadQuery.executeDatabaseQuery(ObjectLevelReadQuery.java:1074)
        at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:736)
        at org.eclipse.persistence.queries.ObjectLevelReadQuery.execute(ObjectLevelReadQuery.java:1034)
        at org.eclipse.persistence.queries.ReadAllQuery.execute(ReadAllQuery.java:380)
        at org.eclipse.persistence.queries.ObjectLevelReadQuery.executeInUnitOfWork(ObjectLevelReadQuery.java:1112)
        at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2909)
        at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1291)
        at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1273)
        at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1247)
        at org.eclipse.persistence.internal.jpa.EJBQueryImpl.executeReadQuery(EJBQueryImpl.java:479)
        at org.eclipse.persistence.internal.jpa.EJBQueryImpl.getResultList(EJBQueryImpl.java:714)
*/

查看使用失败的条件api查询发出的sql,并与使用jpa字符串查询执行查询时发出的sql进行比较。

条件查询

   SELECT DISTINCT t0.ID, t0.SERVICE_USER_TYPE, t0.TITLE, t0.DOB, t0.GENDER, t0.DISABILITY, t0.ETHNICITY, t1.ID, t1.EMPLOYMENT, t1.INFO_PACK_REQUIRED, t1.HOME_PHONE, t1.OTHER_LANGUAGE, t1.REFERRER, t1.MOBILE_PHONE, t1.LONE_PARENT, t1.GP_PRACTICE, t1.CONTACTABLE, t1.WORK_PHONE, t1.BABY_DUE_DATE, t1.ENGLISH_LEVEL 
FROM SERVICE_USER_ADDRESS t3, ADDRESS t2, ADULT t1, SERVICE_USER t0 
WHERE (((? = t2.ID) AND ((t1.ID = t0.ID) AND (t0.SERVICE_USER_TYPE = ?))) 
AND ((t3.SERVICE_USER_ID = t0.ID) AND (t2.ID = t3.ADDRESS_ID)))

JPA字符串查询

  SELECT DISTINCT t0.ID, t0.SERVICE_USER_TYPE, t0.TITLE, t0.DOB, t0.GENDER, t0.DISABILITY, t0.ETHNICITY, t1.ID, t1.EMPLOYMENT, t1.INFO_PACK_REQUIRED, t1.HOME_PHONE, t1.OTHER_LANGUAGE, t1.REFERRER, t1.MOBILE_PHONE, t1.LONE_PARENT, t1.GP_PRACTICE, t1.CONTACTABLE, t1.WORK_PHONE, t1.BABY_DUE_DATE, t1.ENGLISH_LEVEL
FROM SERVICE_USER_ADDRESS t3, ADDRESS t2, ADULT t1, SERVICE_USER t0 
WHERE (((? = t2.ID) AND ((t1.ID = t0.ID) AND (t0.SERVICE_USER_TYPE = ?))) 
AND ((t3.SERVICE_USER_ID = t0.ID) AND (t2.ID = t3.ADDRESS_ID)))

SELECT DISTINCT t0.ID, t0.SERVICE_USER_TYPE, t0.TITLE, t0.DOB, t0.GENDER, t0.DISABILITY, t0.ETHNICITY, t1.ID 
FROM SERVICE_USER_ADDRESS t3, ADDRESS t2, CHILD t1, SERVICE_USER t0 WHERE (((? = t2.ID) AND ((t1.ID = t0.ID) AND (t0.SERVICE_USER_TYPE = ?))) AND ((t3.SERVICE_USER_ID = t0.ID) AND (t2.ID = t3.ADDRESS_ID)))

我可以看到,处理ServiceUser的Adult子类的第一部分在两种情况下是相同的,但是当涉及Child子类时,Criteria查询将抛出

 [EL Warning]: 2010-12-20 )--java.lang.NullPointerException
        at org.eclipse.persistence.descriptors.InheritancePolicy.selectAllRowUsingDefaultMultipleTableSubclassRead(InheritancePolicy.java:1355)

这可能是Eclipselink的错误吗?

1 个答案:

答案 0 :(得分:0)

是的,这确实是Eclipselink的错误

 <dependency>
     <groupId>org.eclipse.persistence</groupId>
     <artifactId>eclipselink</artifactId>
     <version>2.1.1</version>
     <scope>provided</scope>
 </dependency>

更改继承策略
@Inheritance(strategy = InheritanceType.JOINED)

@Inheritance(strategy = InheritanceType.SINGLE_TABLE)

在抽象基类SERVICE_USER上提供了一种解决方法,在我的情况下是可以的。