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

发布于 2024-10-08 10:45:28 字数 7841 浏览 4 评论 0原文

我在将 JPA 查询转换为使用 Criteria API 时遇到问题

我有以下查询,尝试查找与传递的地址参数匹配的 ServiceUser。 ServiceUser 是一个抽象实体,具有具体的子类 Child 和 Adult。我在 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;
}

但是,如果我尝试用以下使用生成的元模型和类型化查询的函数替换该函数,那么我会收到一个异常,

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 的错误吗?

I'm having trouble converting a JPA query to the use the Criteria API

I have the following query that attempts to find a ServiceUser matching a passed address parameter. ServiceUser is an abstract entity with concrete subclasses Child and Adult. I'm using the joined inheritance strategy on the ServiceUser class.

Everything works fine when I call this method.

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

But, if I try to replace the function with the following that uses the generated metamodel and a typedquery then I am getting an exception

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

Here is the stacktrace will Eclipslink logging. There seems to be an NulPointerException being thrown but I'm not sure why?

 /**
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)
*/

Looking at the sql that gets issued with the failing criteria api query and comparing with the sql that gets issued when I perform the query with the jpa string query.

Criteria Query

   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 String Query

  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)))

and

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)))

I can see that the first part that deals with the Adult subclass of ServiceUser is identical in both cases but when it comes to the Child subclass the Criteria query throws

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

Could this be a bug with Eclipselink?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

肩上的翅膀 2024-10-15 10:45:28

是的,这确实似乎是 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 的

Yes this indeed appears to be a bug with Eclipselink

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

Changing the inheritance strategy from

@Inheritance(strategy = InheritanceType.JOINED)

to

@Inheritance(strategy = InheritanceType.SINGLE_TABLE)

on the abstract base class SERVICE_USER provides a workaround that in my case is ok.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文