嵌套连接的Eclipselink-QueryException

时间:2018-01-02 15:53:55

标签: jpa eclipselink

我有一个非常简单的数据模型的查询,它抛出org.eclipse.persistence.exceptions.QueryException,我不明白为什么。

这是设置。我有一个数据模型,其中Person可以有一个Address和多个Job。每个作业本身也可以有很多Address个es。每个关系都是单向的。并且每个关系都是可选的(如果需要,我可以附加源代码)。

         Person 
         1 / \ 1
          /   \
    0..1 /     \ *
   Address     Job
                 \ 1
                  \
                   \ *
                    Address

我的目标是创建一个包含所有相关工作和人员的所有地址的列表。我想通过一个数据库查询来实现这一目标。最后,我需要一些像Map<Address, Pair<Set<Person>, Set<Job>>>这样的数据结构(其中Pair就是我。e。org.apache.commons.lang3.tuple.Pair

所以我加入了所有符合此标准的实体。

CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery query = builder.createQuery();

Root<Person> personRoot = query.from(Person.class);
Join<Person, Address> joinPersonAddress = personRoot.join(Person_.address, JoinType.LEFT);
Join<Person, Job> joinPersonJob = personRoot.join(Person_.jobs, JoinType.LEFT);
Join<Job, Address> joinJobAddress = joinPersonJob.join(Job_.addresses, JoinType.LEFT);

query.multiselect(personRoot, joinPersonAddress, joinPersonJob, joinJobAddress);
Query q = em.createQuery(query);
List<Object[/*Person, Address, Job, Address*/]> result = q.getResultList();

但是在最后一行我得到了一个例外。

Exception [EclipseLink-6044] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.QueryException
Exception Description: The primary key read from the row [DatabaseRecord(
    nullJoin_job.ID => null
    nullJoin_job.JOBNAME => null
    nullJoin_ADDRESS.ID => null
    nullJoin_ADDRESS.CITY => null
    nullJoin_ADDRESS.STREET => null)] during the execution of the query was detected to be null.  Primary keys must not contain null.
Query: ReportQuery(referenceClass=Person sql="SELECT t0.ID, t0.PERSON_ID, t1.ID, t1.CITY, t1.STREET, t2.ID, t2.JOBNAME, t3.ID, t3.CITY, t3.STREET FROM nullJoin_person t0 LEFT OUTER JOIN nullJoin_ADDRESS t1 ON (t1.ID = t0.PERSON_ID) LEFT OUTER JOIN nullJoin_job t2 ON (t2.PERSON_ID = t0.ID) LEFT OUTER JOIN nullJoin_ADDRESS t3 ON (t3.JOB_ID = t2.ID)")
    at org.eclipse.persistence.exceptions.QueryException.nullPrimaryKeyInBuildingObject(QueryException.java:916)
    at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildObject(ObjectBuilder.java:613)
    at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildObject(ObjectBuilder.java:587)
    at org.eclipse.persistence.queries.ReportQueryResult.processItem(ReportQueryResult.java:208)
    at org.eclipse.persistence.queries.ReportQueryResult.buildResult(ReportQueryResult.java:143)
    at org.eclipse.persistence.queries.ReportQueryResult.<init>(ReportQueryResult.java:78)
    at org.eclipse.persistence.queries.ReportQuery.buildObject(ReportQuery.java:593)
    at org.eclipse.persistence.queries.ReportQuery.buildObjects(ReportQuery.java:644)
    at org.eclipse.persistence.queries.ReportQuery.executeDatabaseQuery(ReportQuery.java:847)
    at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:899)
    at org.eclipse.persistence.queries.ObjectLevelReadQuery.execute(ObjectLevelReadQuery.java:1114)
    at org.eclipse.persistence.queries.ReadAllQuery.execute(ReadAllQuery.java:402)
    at org.eclipse.persistence.queries.ObjectLevelReadQuery.executeInUnitOfWork(ObjectLevelReadQuery.java:1202)
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2894)
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1797)
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1779)
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1744)
    at org.eclipse.persistence.internal.jpa.QueryImpl.executeReadQuery(QueryImpl.java:258)
    at org.eclipse.persistence.internal.jpa.QueryImpl.getResultList(QueryImpl.java:468)
    at test.dao.Dao.test(Dao.java:111)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    ...
    ...

我不明白这个例外。如果我在我的数据库工具中执行打印的SQL语句,它就可以作为一个魅力。

目前我执行两个查询,一个用于加入具有地址的人,另一个用于加入具有地址的作业。之后,我在代码中创建Map<Address, Pair<Set<Person>, Set<Job>>>

所以只是为了好奇,为什么分别抛出异常是否有办法解决这个问题,以便我最终只能使用一个数据库查询?

1 个答案:

答案 0 :(得分:0)

看起来像ObjectBuilder,一个处理查询结果并构建结果对象的内部类,无法处理null结果。

您可以通过在没有空关系的数据库上测试查询来确认这一点(即没有无地址人员和工作)。它应该适用于这些情况。

我建议在尝试使用其他JPA提供程序后向eclipselink打开一个错误。

作为一种解决方法,您可以构建一个返回Tuple而不是对象的查询:

CriteriaQuery query = builder.createQuery(Tuple.class);
...
query.multiselect(personRoot, joinPersonAddress, joinPersonJob, joinJobAddress);
TypedQuery<Tuple> tq = em.createQuery(query);