2012-02-29 56 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