【发布时间】:2019-07-26 14:37:16
【问题描述】:
我在将 SQL 查询转换为 JPQL 时遇到问题。有一个表 CASE_FORM,其状态可以是“新”、“草稿”等。还有 3 列:类别、案例类型和区域(即位置)。我的任务是显示类别、case_type 和 region 的每种组合的每个 case_status 的案例数。
例如,对于某些类别:A,case_type:1 和 region:旧金山 状态为 的案例数新可以是某个整数值,例如 12,状态为 Draft 的案例数可以是 3。
为此,我打算对类别、case_type 和 region 使用分组,然后计算 case_status Draft 的案例数和另一个状态 New 。
下面给出了上述方法的有效 SQL 查询:
SQL:
select cf.CATEGORY_ID, cf.CASE_TYPE_ID, cf.REGION,
(select count(*) from KM_ECM.CASE_FORM where CATEGORY_ID=cf.CATEGORY_ID AND CASE_TYPE_ID=cf.CASE_TYPE_ID AND REGION=cf.REGION AND CASE_STATUS='New') AS NEW,
(select count(*) from KM_ECM.CASE_FORM where CATEGORY_ID=cf.CATEGORY_ID AND CASE_TYPE_ID=cf.CASE_TYPE_ID AND REGION=cf.REGION AND CASE_STATUS='Draft') AS DRAFT
from KM_ECM.CASE_FORM cf
group by cf.CATEGORY_ID, cf.CASE_TYPE_ID, cf.REGION;
由于查询将在基于 Java 的 Web 服务中命中,因此我使用 JPA 和 JPQL 来编写上述查询。对于这个特定任务,JPQL 中的查询如下所示:
JPQL:
@NamedQuery(name="CaseForm.getMainReportData", query="SELECT new com.techlogix.sbp.casemanagement.model.MainReport(c.category, c.caseType, c.region, "
+ "(SELECT count(v) FROM CaseForm v where v.category=c.category AND v.caseType=c.caseType AND v.region=c.region AND v.caseStatus='New'),"
+ "(SELECT count(v) FROM CaseForm v where v.category=c.category AND v.caseType=c.caseType AND v.region=c.region AND v.caseStatus='Draft')"
+ ") "
+ "FROM CaseForm c "
+ "GROUP BY c.category, c.caseType, c.region")
JPQL 查询背后的想法与上面提到的 SQL 完全相同。唯一的补充是 JPQL 查询将数据存储在自定义 Bean 类 MainReport 中。
但是,在执行时,查询中断并引发以下异常,
org.apache.openjpa.persistence.ArgumentException:您的查询无效。您的 select 和 having 子句必须只包含也出现在您的分组子句中的聚合或值
异常的完整堆栈跟踪是:
[3/5/19 12:17:05:718 PKT] 000000c0 BusinessExcep E CNTR0020E: EJB threw an unexpected (non-declared) exception during invocation of method "getMainReport" on bean "BeanId(casemanagement-ear#casemanagement-business-service-impl-1.0.jar#FEODReportService, null)". Exception data: <openjpa-2.2.3-SNAPSHOT-r422266:1764177 nonfatal user error> org.apache.openjpa.persistence.ArgumentException: Your query on type "class com.techlogix.sbp.casemanagement.model.CaseForm" with filter "" is invalid. Your select and having clauses must only include aggregates or values that also appear in your grouping clause.
at org.apache.openjpa.kernel.ExpressionStoreQuery$AbstractExpressionExecutor$ValidateGroupingExpressionVisitor.enter(ExpressionStoreQuery.java:563)
at org.apache.openjpa.kernel.exps.Val.acceptVisit(Val.java:119)
at org.apache.openjpa.jdbc.kernel.exps.CompareEqualExpression.acceptVisit(CompareEqualExpression.java:138)
at org.apache.openjpa.jdbc.kernel.exps.AndExpression.acceptVisit(AndExpression.java:80)
at org.apache.openjpa.jdbc.kernel.exps.SubQ.acceptVisit(SubQ.java:241)
at org.apache.openjpa.kernel.ExpressionStoreQuery$AbstractExpressionExecutor$ValidateGroupingExpressionVisitor.validate(ExpressionStoreQuery.java:544)
at org.apache.openjpa.kernel.ExpressionStoreQuery$AbstractExpressionExecutor.validate(ExpressionStoreQuery.java:335)
at org.apache.openjpa.kernel.QueryImpl.compile(QueryImpl.java:591)
at org.apache.openjpa.persistence.EntityManagerImpl.createNamedQuery(EntityManagerImpl.java:1038)
at com.ibm.ws.persistence.EntityManagerImpl.createNamedQuery(EntityManagerImpl.java:116)
at com.ibm.ws.persistence.EntityManagerImpl.createNamedQuery(EntityManagerImpl.java:50)
at org.apache.openjpa.persistence.EntityManagerImpl.createNamedQuery(EntityManagerImpl.java:1017)
at com.ibm.ws.persistence.EntityManagerImpl.createNamedQuery(EntityManagerImpl.java:127)
at com.ibm.ws.jpa.management.JPATxEmInvocation.createNamedQuery(JPATxEmInvocation.java:340)
at com.ibm.ws.jpa.management.JPAEntityManager.createNamedQuery(JPAEntityManager.java:543)
at com.techlogix.sbp.casemanagement.dao.impl.CaseFormDaoImpl.getMainReportData(CaseFormDaoImpl.java:495)
at com.techlogix.sbp.casemanagement.service.impl.FEODReportServiceImpl.getMainReport(FEODReportServiceImpl.java:171)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:95)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
at java.lang.reflect.Method.invoke(Method.java:508)
at com.ibm.ejs.container.EJSContainer.invokeProceed(EJSContainer.java:5798)
at com.ibm.ejs.container.interceptors.InvocationContextImpl.proceed(InvocationContextImpl.java:569)
at org.apache.webbeans.ejb.common.interceptor.OpenWebBeansEjbInterceptor.callInterceptorsAndDecorators(OpenWebBeansEjbInterceptor.java:559)
at org.apache.webbeans.ejb.common.interceptor.OpenWebBeansEjbInterceptor.callToOwbInterceptors(OpenWebBeansEjbInterceptor.java:222)
at sun.reflect.GeneratedMethodAccessor16.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
at java.lang.reflect.Method.invoke(Method.java:508)
at com.ibm.ejs.container.interceptors.InterceptorProxy.invokeInterceptor(InterceptorProxy.java:227)
at com.ibm.ejs.container.interceptors.InvocationContextImpl.proceed(InvocationContextImpl.java:549)
at org.apache.webbeans.ejb.WSEJBInterceptor.callToOwbInterceptors(WSEJBInterceptor.java:152)
at sun.reflect.GeneratedMethodAccessor13.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
at java.lang.reflect.Method.invoke(Method.java:508)
at com.ibm.ejs.container.interceptors.InterceptorProxy.invokeInterceptor(InterceptorProxy.java:227)
at com.ibm.ejs.container.interceptors.InvocationContextImpl.proceed(InvocationContextImpl.java:549)
at com.ibm.ejs.container.interceptors.InvocationContextImpl.doAroundInvoke(InvocationContextImpl.java:230)
at com.ibm.ejs.container.EJSContainer.invoke(EJSContainer.java:5689)
at com.techlogix.sbp.casemanagement.service.EJSRemote0SLFEODReportService_81b95711.getMainReport(EJSRemote0SLFEODReportService_81b95711.java)
at com.techlogix.sbp.casemanagement.service._FEODReportService_Stub.getMainReport(_FEODReportService_Stub.java:1)
at com.techlogix.sbp.casemanagement.soap.FEODReportsWebService.getMainReport(FEODReportsWebService.java:120)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:95)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
at java.lang.reflect.Method.invoke(Method.java:508)
at org.apache.axis2.jaxws.server.dispatcher.JavaDispatcher.invokeTargetOperation(JavaDispatcher.java:120)
at org.apache.axis2.jaxws.server.dispatcher.JavaBeanDispatcher.invoke(JavaBeanDispatcher.java:118)
at org.apache.axis2.jaxws.server.EndpointController.invoke(EndpointController.java:111)
at org.apache.axis2.jaxws.server.JAXWSMessageReceiver.receive(JAXWSMessageReceiver.java:161)
at org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:212)
at org.apache.axis2.transport.http.HTTPTransportUtils.processHTTPPostRequest(HTTPTransportUtils.java:172)
at com.ibm.ws.websvcs.transport.http.WASAxis2Servlet.doPost(WASAxis2Servlet.java:1632)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:595)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:668)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1233)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:782)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:481)
at com.ibm.ws.webcontainer.servlet.ServletWrapperImpl.handleRequest(ServletWrapperImpl.java:178)
at com.ibm.ws.webcontainer.filter.WebAppFilterManager.invokeFilters(WebAppFilterManager.java:1114)
at com.ibm.ws.webcontainer.servlet.CacheServletWrapper.handleRequest(CacheServletWrapper.java:87)
at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:949)
at com.ibm.ws.webcontainer.WSWebContainer.handleRequest(WSWebContainer.java:1817)
at com.ibm.ws.webcontainer.channel.WCChannelLink.ready(WCChannelLink.java:200)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:463)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleNewRequest(HttpInboundLink.java:530)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.processRequest(HttpInboundLink.java:316)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.ready(HttpInboundLink.java:287)
at com.ibm.ws.tcp.channel.impl.NewConnectionInitialReadCallback.sendToDiscriminators(NewConnectionInitialReadCallback.java:214)
at com.ibm.ws.tcp.channel.impl.NewConnectionInitialReadCallback.complete(NewConnectionInitialReadCallback.java:113)
at com.ibm.ws.tcp.channel.impl.AioReadCompletionListener.futureCompleted(AioReadCompletionListener.java:175)
at com.ibm.io.async.AbstractAsyncFuture.invokeCallback(AbstractAsyncFuture.java:217)
at com.ibm.io.async.AsyncChannelFuture.fireCompletionActions(AsyncChannelFuture.java:161)
at com.ibm.io.async.AsyncFuture.completed(AsyncFuture.java:138)
at com.ibm.io.async.ResultHandler.complete(ResultHandler.java:204)
at com.ibm.io.async.ResultHandler.runEventProcessingLoop(ResultHandler.java:775)
at com.ibm.io.async.ResultHandler$2.run(ResultHandler.java:905)
at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1892)
[3/5/19 12:17:05:733 PKT] 000000c0 AxisEngine E org.apache.axis2.engine.AxisEngine receive null
org.apache.axis2.AxisFault
at org.apache.axis2.jaxws.server.dispatcher.JavaBeanDispatcher.createFaultResponse(JavaBeanDispatcher.java:407)
at org.apache.axis2.jaxws.server.dispatcher.JavaBeanDispatcher.invoke(JavaBeanDispatcher.java:138)
at org.apache.axis2.jaxws.server.EndpointController.invoke(EndpointController.java:111)
at org.apache.axis2.jaxws.server.JAXWSMessageReceiver.receive(JAXWSMessageReceiver.java:161)
at org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:212)
at org.apache.axis2.transport.http.HTTPTransportUtils.processHTTPPostRequest(HTTPTransportUtils.java:172)
at com.ibm.ws.websvcs.transport.http.WASAxis2Servlet.doPost(WASAxis2Servlet.java:1632)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:595)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:668)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1233)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:782)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:481)
at com.ibm.ws.webcontainer.servlet.ServletWrapperImpl.handleRequest(ServletWrapperImpl.java:178)
at com.ibm.ws.webcontainer.filter.WebAppFilterManager.invokeFilters(WebAppFilterManager.java:1114)
at com.ibm.ws.webcontainer.servlet.CacheServletWrapper.handleRequest(CacheServletWrapper.java:87)
at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:949)
at com.ibm.ws.webcontainer.WSWebContainer.handleRequest(WSWebContainer.java:1817)
at com.ibm.ws.webcontainer.channel.WCChannelLink.ready(WCChannelLink.java:200)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:463)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleNewRequest(HttpInboundLink.java:530)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.processRequest(HttpInboundLink.java:316)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.ready(HttpInboundLink.java:287)
at com.ibm.ws.tcp.channel.impl.NewConnectionInitialReadCallback.sendToDiscriminators(NewConnectionInitialReadCallback.java:214)
at com.ibm.ws.tcp.channel.impl.NewConnectionInitialReadCallback.complete(NewConnectionInitialReadCallback.java:113)
at com.ibm.ws.tcp.channel.impl.AioReadCompletionListener.futureCompleted(AioReadCompletionListener.java:175)
at com.ibm.io.async.AbstractAsyncFuture.invokeCallback(AbstractAsyncFuture.java:217)
at com.ibm.io.async.AsyncChannelFuture.fireCompletionActions(AsyncChannelFuture.java:161)
at com.ibm.io.async.AsyncFuture.completed(AsyncFuture.java:138)
at com.ibm.io.async.ResultHandler.complete(ResultHandler.java:204)
at com.ibm.io.async.ResultHandler.runEventProcessingLoop(ResultHandler.java:775)
at com.ibm.io.async.ResultHandler$2.run(ResultHandler.java:905)
at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1892)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:95)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
at java.lang.reflect.Method.invoke(Method.java:508)
at org.apache.axis2.jaxws.server.dispatcher.JavaDispatcher.invokeTargetOperation(JavaDispatcher.java:120)
at org.apache.axis2.jaxws.server.dispatcher.JavaBeanDispatcher.invoke(JavaBeanDispatcher.java:118)
... 30 more
Caused by: javax.ejb.EJBException: See nested exception; nested exception is: <openjpa-2.2.3-SNAPSHOT-r422266:1764177 nonfatal user error> org.apache.openjpa.persistence.ArgumentException: Your query on type "class com.techlogix.sbp.casemanagement.model.CaseForm" with filter "SELECT new com.techlogix.sbp.casemanagement.model.MainReport(c.category, c.caseType, c.region, (SELECT count(v) FROM CaseForm v where v.category=c.category AND v.caseType=c.caseType AND v.region=c.region AND v.caseStatus='New'), (SELECT count(v) FROM CaseForm v where v.category=c.category AND v.caseType=c.caseType AND v.region=c.region AND v.caseStatus='Draft')) FROM CaseForm c GROUP BY c.category, c.caseType, c.region" is invalid. Your select and having clauses must only include aggregates or values that also appear in your grouping clause.
at com.ibm.ejs.container.util.ExceptionUtil.EJBException(ExceptionUtil.java:475)
at com.ibm.ejs.container.util.ExceptionUtil.EJBException(ExceptionUtil.java:365)
at com.ibm.ejs.container.BusinessExceptionMappingStrategy.mapException(BusinessExceptionMappingStrategy.java:392)
at com.ibm.ejs.container.BusinessExceptionMappingStrategy.setUncheckedException(BusinessExceptionMappingStrategy.java:554)
at com.ibm.ejs.container.EJSDeployedSupport.setUncheckedLocalException(EJSDeployedSupport.java:570)
at com.techlogix.sbp.casemanagement.service.EJSRemote0SLFEODReportService_81b95711.getMainReport(EJSRemote0SLFEODReportService_81b95711.java)
at com.techlogix.sbp.casemanagement.service._FEODReportService_Stub.getMainReport(_FEODReportService_Stub.java:1)
at com.techlogix.sbp.casemanagement.soap.FEODReportsWebService.getMainReport(FEODReportsWebService.java:120)
... 36 more
Caused by: <openjpa-2.2.3-SNAPSHOT-r422266:1764177 nonfatal user error> org.apache.openjpa.persistence.ArgumentException: Your query on type "class com.techlogix.sbp.casemanagement.model.CaseForm" with filter "SELECT new com.techlogix.sbp.casemanagement.model.MainReport(c.category, c.caseType, c.region, (SELECT count(v) FROM CaseForm v where v.category=c.category AND v.caseType=c.caseType AND v.region=c.region AND v.caseStatus='New'), (SELECT count(v) FROM CaseForm v where v.category=c.category AND v.caseType=c.caseType AND v.region=c.region AND v.caseStatus='Draft')) FROM CaseForm c GROUP BY c.category, c.caseType, c.region" is invalid. Your select and having clauses must only include aggregates or values that also appear in your grouping clause.
at org.apache.openjpa.kernel.ExpressionStoreQuery$AbstractExpressionExecutor$ValidateGroupingExpressionVisitor.enter(ExpressionStoreQuery.java:563)
at org.apache.openjpa.kernel.exps.Val.acceptVisit(Val.java:119)
at org.apache.openjpa.jdbc.kernel.exps.CompareEqualExpression.acceptVisit(CompareEqualExpression.java:138)
at org.apache.openjpa.jdbc.kernel.exps.AndExpression.acceptVisit(AndExpression.java:80)
at org.apache.openjpa.jdbc.kernel.exps.SubQ.acceptVisit(SubQ.java:241)
at org.apache.openjpa.kernel.ExpressionStoreQuery$AbstractExpressionExecutor$ValidateGroupingExpressionVisitor.validate(ExpressionStoreQuery.java:544)
at org.apache.openjpa.kernel.ExpressionStoreQuery$AbstractExpressionExecutor.validate(ExpressionStoreQuery.java:335)
at org.apache.openjpa.kernel.QueryImpl.compile(QueryImpl.java:591)
at org.apache.openjpa.persistence.EntityManagerImpl.createNamedQuery(EntityManagerImpl.java:1038)
at com.ibm.ws.persistence.EntityManagerImpl.createNamedQuery(EntityManagerImpl.java:116)
at com.ibm.ws.persistence.EntityManagerImpl.createNamedQuery(EntityManagerImpl.java:50)
at org.apache.openjpa.persistence.EntityManagerImpl.createNamedQuery(EntityManagerImpl.java:1017)
at com.ibm.ws.persistence.EntityManagerImpl.createNamedQuery(EntityManagerImpl.java:127)
at com.ibm.ws.jpa.management.JPATxEmInvocation.createNamedQuery(JPATxEmInvocation.java:340)
at com.ibm.ws.jpa.management.JPAEntityManager.createNamedQuery(JPAEntityManager.java:543)
at com.techlogix.sbp.casemanagement.dao.impl.CaseFormDaoImpl.getMainReportData(CaseFormDaoImpl.java:495)
at com.techlogix.sbp.casemanagement.service.impl.FEODReportServiceImpl.getMainReport(FEODReportServiceImpl.java:171)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:95)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
at java.lang.reflect.Method.invoke(Method.java:508)
at com.ibm.ejs.container.EJSContainer.invokeProceed(EJSContainer.java:5798)
at com.ibm.ejs.container.interceptors.InvocationContextImpl.proceed(InvocationContextImpl.java:569)
at org.apache.webbeans.ejb.common.interceptor.OpenWebBeansEjbInterceptor.callInterceptorsAndDecorators(OpenWebBeansEjbInterceptor.java:559)
at org.apache.webbeans.ejb.common.interceptor.OpenWebBeansEjbInterceptor.callToOwbInterceptors(OpenWebBeansEjbInterceptor.java:222)
at sun.reflect.GeneratedMethodAccessor16.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
at java.lang.reflect.Method.invoke(Method.java:508)
at com.ibm.ejs.container.interceptors.InterceptorProxy.invokeInterceptor(InterceptorProxy.java:227)
at com.ibm.ejs.container.interceptors.InvocationContextImpl.proceed(InvocationContextImpl.java:549)
at org.apache.webbeans.ejb.WSEJBInterceptor.callToOwbInterceptors(WSEJBInterceptor.java:152)
at sun.reflect.GeneratedMethodAccessor13.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
at java.lang.reflect.Method.invoke(Method.java:508)
at com.ibm.ejs.container.interceptors.InterceptorProxy.invokeInterceptor(InterceptorProxy.java:227)
at com.ibm.ejs.container.interceptors.InvocationContextImpl.proceed(InvocationContextImpl.java:549)
at com.ibm.ejs.container.interceptors.InvocationContextImpl.doAroundInvoke(InvocationContextImpl.java:230)
at com.ibm.ejs.container.EJSContainer.invoke(EJSContainer.java:5689)
... 39 more
【问题讨论】: