我有一个非常简单的数据模型的查询,它抛出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>>>
。
所以只是为了好奇,为什么分别抛出异常是否有办法解决这个问题,以便我最终只能使用一个数据库查询?
答案 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);