我正在从Hibernate移植。 JPQL语句中的SIZE函数有什么问题(假设映射是正确的)?:
SELECT NEW de.poyry.pqgenerator.view.PqListItem(
pq.id,
pq.name,
pq.submissionDate,
pe.firstName,
pe.lastName,
SIZE(pa))
FROM Prequalification pq
JOIN pq.user us
JOIN us.person pe
LEFT JOIN pq.partnerships pa
LEFT JOIN pa.company co
GROUP BY pq.id
这是构造函数签名(唯一的构造函数):
public PqListItem(Integer id, String name, Date submissionDate,
String ownerFirstName, String ownerLastName,
Integer numPartnerships)
查询结果为:
Caused by: Exception [EclipseLink-8023] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.JPQLException
Exception Description: Syntax error parsing the query [^^...].
Internal Exception: org.eclipse.persistence.internal.libraries.antlr.runtime.EarlyExitException
at org.eclipse.persistence.exceptions.JPQLException.syntaxError(JPQLException.java:352)
at org.eclipse.persistence.internal.jpa.parsing.jpql.JPQLParser.handleRecognitionException(JPQLParser.java:354)
at org.eclipse.persistence.internal.jpa.parsing.jpql.JPQLParser.addError(JPQLParser.java:246)
at org.eclipse.persistence.internal.jpa.parsing.jpql.JPQLParser.reportError(JPQLParser.java:363)
at org.eclipse.persistence.internal.jpa.parsing.jpql.antlr.JPQLParser.pathExpression(JPQLParser.java:2894)
at org.eclipse.persistence.internal.jpa.parsing.jpql.antlr.JPQLParser.collectionValuedPathExpression(JPQLParser.java:2624)
at org.eclipse.persistence.internal.jpa.parsing.jpql.antlr.JPQLParser.size(JPQLParser.java:7660)
at org.eclipse.persistence.internal.jpa.parsing.jpql.antlr.JPQLParser.functionsReturningNumerics(JPQLParser.java:6710)
at org.eclipse.persistence.internal.jpa.parsing.jpql.antlr.JPQLParser.arithmeticPrimary(JPQLParser.java:4762)
at org.eclipse.persistence.internal.jpa.parsing.jpql.antlr.JPQLParser.arithmeticFactor(JPQLParser.java:4660)
at org.eclipse.persistence.internal.jpa.parsing.jpql.antlr.JPQLParser.arithmeticTerm(JPQLParser.java:4546)
at org.eclipse.persistence.internal.jpa.parsing.jpql.antlr.JPQLParser.simpleArithmeticExpression(JPQLParser.java:4462)
at org.eclipse.persistence.internal.jpa.parsing.jpql.antlr.JPQLParser.scalarExpression(JPQLParser.java:4834)
at org.eclipse.persistence.internal.jpa.parsing.jpql.antlr.JPQLParser.constructorItem(JPQLParser.java:1980)
at org.eclipse.persistence.internal.jpa.parsing.jpql.antlr.JPQLParser.constructorExpression(JPQLParser.java:1849)
at org.eclipse.persistence.internal.jpa.parsing.jpql.antlr.JPQLParser.selectExpression(JPQLParser.java:1300)
at org.eclipse.persistence.internal.jpa.parsing.jpql.antlr.JPQLParser.selectItem(JPQLParser.java:1169)
at org.eclipse.persistence.internal.jpa.parsing.jpql.antlr.JPQLParser.selectClause(JPQLParser.java:1081)
at org.eclipse.persistence.internal.jpa.parsing.jpql.antlr.JPQLParser.selectStatement(JPQLParser.java:359)
at org.eclipse.persistence.internal.jpa.parsing.jpql.antlr.JPQLParser.document(JPQLParser.java:281)
at org.eclipse.persistence.internal.jpa.parsing.jpql.JPQLParser.parse(JPQLParser.java:134)
at org.eclipse.persistence.internal.jpa.parsing.jpql.JPQLParser.buildParseTree(JPQLParser.java:95)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.buildEJBQLDatabaseQuery(EJBQueryImpl.java:215)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.buildEJBQLDatabaseQuery(EJBQueryImpl.java:190)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.<init>(EJBQueryImpl.java:142)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.<init>(EJBQueryImpl.java:126)
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.createQuery(EntityManagerImpl.java:1475)
... 139 more
Caused by: org.eclipse.persistence.internal.libraries.antlr.runtime.EarlyExitException
at org.eclipse.persistence.internal.jpa.parsing.jpql.antlr.JPQLParser.pathExpression(JPQLParser.java:2882)
... 161 more
SIZE(pa)
似乎会导致问题。当改为SIZE(pq.partnerships)
时,我得到:
Caused by: Exception [EclipseLink-6137] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.QueryException
Exception Description: An Exception was thrown while executing a ReportQuery with a constructor expression: java.lang.NoSuchMethodException: de.poyry.pqgenerator.view.PqListItem.<init>(java.lang.Integer, java.lang.String, java.util.Date, java.lang.String, java.lang.String, int)
Query: ReportQuery(referenceClass=Prequalification jpql="SELECT NEW de.poyry.pqgenerator.view.PqListItem(pq.id, pq.name, pq.submissionDate, pe.firstName, pe.lastName, SIZE(pq.partnerships)) FROM Prequalification pq JOIN pq.user us JOIN us.person pe LEFT JOIN pq.partnerships pa LEFT JOIN pa.company co GROUP BY pq.id")
Default FetchGroup(){id, partnerships, submissionDate, nodes, designSheets, name, statuses, group, user, tendering, isLocked}
at org.eclipse.persistence.exceptions.QueryException.exceptionWhileUsingConstructorExpression(QueryException.java:494)
at org.eclipse.persistence.queries.ConstructorReportItem.initialize(ConstructorReportItem.java:188)
at org.eclipse.persistence.queries.ReportQuery.prepare(ReportQuery.java:1044)
at org.eclipse.persistence.queries.DatabaseQuery.checkPrepare(DatabaseQuery.java:598)
at org.eclipse.persistence.queries.ObjectLevelReadQuery.checkPrepare(ObjectLevelReadQuery.java:839)
at org.eclipse.persistence.queries.DatabaseQuery.prepareCall(DatabaseQuery.java:1719)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.buildEJBQLDatabaseQuery(EJBQueryImpl.java:268)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.buildEJBQLDatabaseQuery(EJBQueryImpl.java:190)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.<init>(EJBQueryImpl.java:142)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.<init>(EJBQueryImpl.java:126)
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.createQuery(EntityManagerImpl.java:1475)
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.createQuery(EntityManagerImpl.java:1497)
at com.sun.enterprise.container.common.impl.EntityManagerWrapper.createQuery(EntityManagerWrapper.java:468)
at de.poyry.pqgenerator.service.PqService.findAllPqs(PqService.java:60)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.glassfish.ejb.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1052)
at org.glassfish.ejb.security.application.EJBSecurityManager.invoke(EJBSecurityManager.java:1124)
at com.sun.ejb.containers.BaseContainer.invokeBeanMethod(BaseContainer.java:5366)
at com.sun.ejb.EjbInvocation.invokeBeanMethod(EjbInvocation.java:619)
at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:800)
at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:571)
at org.jboss.weld.ejb.SessionBeanInterceptor.aroundInvoke(SessionBeanInterceptor.java:46)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:861)
at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:800)
at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:571)
at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.doAround(SystemInterceptorProxy.java:162)
at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.aroundInvoke(SystemInterceptorProxy.java:144)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:861)
at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:800)
at com.sun.ejb.containers.interceptors.InterceptorManager.intercept(InterceptorManager.java:370)
at com.sun.ejb.containers.BaseContainer.__intercept(BaseContainer.java:5338)
at com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:5326)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:214)
... 106 more
看起来没有发生自动装箱?最后一个构造函数参数的类型是Integer。奇怪的是,它应该适用于IMO。
有人可以帮忙吗?我在GlassFish 3.1.1上使用EclipseLink 2.3.2。
如何从查询中正确确定合作伙伴的数量? JPA在这里定义了什么?
答案 0 :(得分:3)
SIZE
函数在jpa规范中定义为
functions_returning_numerics::=
SIZE(collection_valued_path_expression)
collection_valued_path_expression ::=
general_identification_variable.{single_valued_object_field.}*collection_valued_field
这意味着您必须将实际属性传递给SIZE
函数而不是仅传递变量名称。您可以尝试以下查询:
SELECT NEW de.poyry.pqgenerator.view.PqListItem(
pq.id,
pq.name,
pq.submissionDate,
pe.firstName,
pe.lastName,
SIZE(pq.partnerships))
FROM Prequalification pq
JOIN pq.user us
JOIN us.person pe
GROUP BY pq.id, pq.name, pq.submissionDate, pe.firstName, pe.lastName
请注意,我还删除了pa.company
和pq.partnerships
的连接,因为它们未被使用,并根据JPA和SQL的要求将非聚合字段添加到GROUP BY
表达式标准。
使用
SELECT
时GROUP BY
子句的要求遵循SQL的要求:即any 出现在SELECT
子句中的项目(作为聚合函数或作为参数的参数除外) 聚合函数)也必须出现在GROUP BY
子句中。
答案 1 :(得分:2)
如果你添加一个带有int而不是Integer的构造函数,它是否有效? 这似乎是个问题。
我认为这已在EclipseLink 2.4流中修复,Integer或int现在应该可以工作。