2012-02-29 60 views
1

我从Hibernate移植。这有什么错在JPQL语句大小的功能(假设映射是正确的)?:JPQL:在EclipseLink上导致奇怪异常的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(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在这里定义了什么?

回答

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他们不使用和添加的非集合字段到GROUP BY表达所要求的JPA和SQL标准。

GROUP BY时,使用用于SELECT子句要求遵循这些SQL的:即,显示的SELECT条款(不是作为一个集合函数或作为参数传递给一个 聚集函数其他)在任何 项必须也出现在GROUP BY条款中。

+0

作品,谢谢!请编辑页面。如果你喜欢 – Kawu 2012-02-29 15:14:13

+0

我只看不到为什么我需要'GROUP BY'中的',pq.name,pq.submissionDate,pe.firstName,pe.lastName'字段,因为只有pq.id产生相同的列表PQ项目。 – Kawu 2012-02-29 15:20:33

2

如果添加一个构造函数int的整数,而不是它的工作原理? 这似乎是问题所在。

我认为这是固定在EclipseLink 2.4流,整数或int现在应该工作。

+0

这工作。感谢EclipseLink 2.4信息。 – Kawu 2012-02-29 14:57:01