JPQL抛出即使直接SQL查询有效,也无法确定搜索的case语句的数据类型

时间:2018-02-21 10:25:34

标签: java hibernate jpa jpql

我正在尝试按照以下方式更新表格:

entityManager.createQuery(
        "UPDATE TestCaseExecutionDetailsEntity " +
        " SET status = " +
        " CASE WHEN (runOrder < :runOrder) THEN :completedStatus " +
        "      WHEN (runOrder = :runOrder) THEN :failedStatus " +
        "      WHEN (runOrder > :runOrder) THEN :abortedStatus " +
        " END " +
        " WHERE testExecutionJobId = :jobId")
    .setParameter("jobId", jobId)
    .setParameter("runOrder", runOrder)
    .setParameter("completedStatus", completed.name())
    .setParameter("failedStatus", failed.name())
    .setParameter("abortedStatus", aborted.name())
    .executeUpdate();

对于值jobId = 1037runOrder = 2,它会抛出错误:

  

java.lang.IllegalArgumentException:org.hibernate.QueryException:
  无法确定搜索到的案例陈述的数据类型
  [更新com.pkg.dataaccess.model.TestCaseExecutionDetailsEntity set status = CASE WHEN(runOrder&lt;:runOrder)那么:completedStatus WHEN(runOrder =:runOrder)那么:failedStatus WHEN(runOrder&gt;:runOrder)那么:abortedStatus END WHERE testExecutionJobId =:jobId]

但是如果我尝试直接运行SQL,它运行正常:

UPDATE TEST_CASE_EXECUTION_DETAILS tcxd
SET tcxd.STATUS =
CASE WHEN (tcxd.RUN_ORDER < 2) THEN 'completed'
WHEN (tcxd.RUN_ORDER = 2) THEN 'failed'
WHEN (tcxd.RUN_ORDER > 2) THEN 'aborted'
END
WHERE TEST_EXECUTION_JOB_ID = 1037;

我对为什么会发生这种情况一无所知。否则,我必须在代码库中放置逻辑,这可能会变得混乱。

完整堆栈跟踪 -

java.lang.IllegalArgumentException: org.hibernate.QueryException: Could not determine data type for searched case statement [update com.pkg.dataaccess.model.TestCaseExecutionDetailsEntity tcede  set tcede.status =  CASE WHEN (tcede.runOrder < :runOrder) THEN :completedStatus       WHEN (tcede.runOrder = :runOrder) THEN :failedStatus       WHEN (tcede.runOrder > :runOrder) THEN :abortedStatus  END  WHERE tcede.testExecutionJobId = :jobId]
        at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1679) ~[hibernate-entitymanager-5.1.0.Final.jar:5.1.0.Final]
        at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1602) ~[hibernate-entitymanager-5.1.0.Final.jar:5.1.0.Final]
        at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1608) ~[hibernate-entitymanager-5.1.0.Final.jar:5.1.0.Final]
        at org.hibernate.jpa.spi.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:294) ~[hibernate-entitymanager-5.1.0.Final.jar:5.1.0.Final]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_121]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_121]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_121]
        at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_121]
        at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:347) ~[spring-orm-4.3.10.RELEASE.jar:4.3.10.RELEASE]
        at com.sun.proxy.$Proxy116.createQuery(Unknown Source) ~[?:?]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_121]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_121]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_121]
        at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_121]
        at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:298) ~[spring-orm-4.3.10.RELEASE.jar:4.3.10.RELEASE]
        at com.sun.proxy.$Proxy80.createQuery(Unknown Source) ~[?:?]
        at com.pkg.dataaccess.repository.TestDataAccessorRepository.updateCaseDetailsForFailedJob(TestRunsDataAccessorRepository.java:542) ~[classes/:?]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_121]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_121]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_121]
        at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_121]
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333) ~[spring-aop-4.3.10.RELEASE.jar:4.3.10.RELEASE]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) ~[spring-aop-4.3.10.RELEASE.jar:4.3.10.RELEASE]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) ~[spring-aop-4.3.10.RELEASE.jar:4.3.10.RELEASE]
        at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) ~[spring-aop-4.3.10.RELEASE.jar:4.3.10.RELEASE]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.10.RELEASE.jar:4.3.10.RELEASE]
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213) ~[spring-aop-4.3.10.RELEASE.jar:4.3.10.RELEASE]
        at com.sun.proxy.$Proxy83.updateCaseDetailsForFailedJob(Unknown Source) ~[?:?]
        at com.pkg.rest.controllers.EmailController.get(EmailController.java:51) ~[classes/:?]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_121]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_121]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_121]
        at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_121]
        at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory$1.invoke(ResourceMethodInvocationHandlerFactory.java:81) ~[jersey-server-2.25.jar:?]
        at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:144) ~[jersey-server-2.25.jar:?]
        at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:161) ~[jersey-server-2.25.jar:?]
        at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:160) ~[jersey-server-2.25.jar:?]
        at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:99) ~[jersey-server-2.25.jar:?]
        at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:389) ~[jersey-server-2.25.jar:?]
        at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:347) ~[jersey-server-2.25.jar:?]
        at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:102) ~[jersey-server-2.25.jar:?]
        at org.glassfish.jersey.server.ServerRuntime$2.run(ServerRuntime.java:326) [jersey-server-2.25.jar:?]
        at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271) [jersey-common-2.25.jar:?]
        at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267) [jersey-common-2.25.jar:?]
        at org.glassfish.jersey.internal.Errors.process(Errors.java:315) [jersey-common-2.25.jar:?]
        at org.glassfish.jersey.internal.Errors.process(Errors.java:297) [jersey-common-2.25.jar:?]
        at org.glassfish.jersey.internal.Errors.process(Errors.java:267) [jersey-common-2.25.jar:?]
        at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317) [jersey-common-2.25.jar:?]
        at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:305) [jersey-server-2.25.jar:?]
        at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1154) [jersey-server-2.25.jar:?]
        at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:473) [jersey-container-servlet-core-2.25.jar:?]
        at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:427) [jersey-container-servlet-core-2.25.jar:?]
        at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:388) [jersey-container-servlet-core-2.25.jar:?]
        at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:341) [jersey-container-servlet-core-2.25.jar:?]
        at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:228) [jersey-container-servlet-core-2.25.jar:?]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292) [catalina.jar:8.0.41]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) [catalina.jar:8.0.41]
        at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) [tomcat-websocket.jar:8.0.41]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) [catalina.jar:8.0.41]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) [catalina.jar:8.0.41]
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212) [catalina.jar:8.0.41]
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:94) [catalina.jar:8.0.41]
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:504) [catalina.jar:8.0.41]
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141) [catalina.jar:8.0.41]
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) [catalina.jar:8.0.41]
        at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:620) [catalina.jar:8.0.41]
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) [catalina.jar:8.0.41]
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:509) [catalina.jar:8.0.41]
        at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1104) [tomcat-coyote.jar:8.0.41]
        at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:684) [tomcat-coyote.jar:8.0.41]
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1524) [tomcat-coyote.jar:8.0.41]
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1480) [tomcat-coyote.jar:8.0.41]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [?:1.8.0_121]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [?:1.8.0_121]
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-util.jar:8.0.41]
        at java.lang.Thread.run(Thread.java:745) [?:1.8.0_121]
Caused by: org.hibernate.QueryException: Could not determine data type for searched case statement [update com.pkg.dataaccess.model.TestCaseExecutionDetailsEntity tcede  set tcede.status =  CASE WHEN (tcede.runOrder < :runOrder) THEN :completedStatus       WHEN (tcede.runOrder = :runOrder) THEN :failedStatus       WHEN (tcede.runOrder > :runOrder) THEN :abortedStatus  END  WHERE tcede.testExecutionJobId = :jobId]
        at org.hibernate.QueryException.generateQueryException(QueryException.java:120) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
        at org.hibernate.QueryException.wrapWithQueryString(QueryException.java:103) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
        at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:218) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
        at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:142) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
        at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:115) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
        at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:76) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
        at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:150) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
        at org.hibernate.internal.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:302) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
        at org.hibernate.internal.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:240) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
        at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:1907) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
        at org.hibernate.jpa.spi.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:291) ~[hibernate-entitymanager-5.1.0.Final.jar:5.1.0.Final]
        ... 72 more
Caused by: org.hibernate.QueryException: Could not determine data type for searched case statement
        at org.hibernate.hql.internal.ast.tree.SearchedCaseNode.getDataType(SearchedCaseNode.java:62) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
        at org.hibernate.hql.internal.ast.tree.BinaryLogicOperatorNode.extractDataType(BinaryLogicOperatorNode.java:239) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
        at org.hibernate.hql.internal.ast.tree.BinaryLogicOperatorNode.initialize(BinaryLogicOperatorNode.java:49) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
        at org.hibernate.hql.internal.ast.HqlSqlWalker.prepareLogicOperator(HqlSqlWalker.java:1369) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
        at org.hibernate.hql.internal.ast.HqlSqlWalker.evaluateAssignment(HqlSqlWalker.java:1270) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.assignment(HqlSqlBaseWalker.java:1063) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.setClause(HqlSqlBaseWalker.java:763) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.updateStatement(HqlSqlBaseWalker.java:379) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:267) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
        at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:262) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
        at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:190) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
        at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:142) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
        at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:115) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
        at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:76) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
        at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:150) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
        at org.hibernate.internal.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:302) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
        at org.hibernate.internal.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:240) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
        at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:1907) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
        at org.hibernate.jpa.spi.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:291) ~[hibernate-entitymanager-5.1.0.Final.jar:5.1.0.Final]
        ... 72 more

2 个答案:

答案 0 :(得分:1)

我在下面的查询中遇到了同样的问题。只需在CASE语句中强制转换变量就可以了:

SELECT SUM(
    CASE WHEN type = 'SOME_TYPE' THEN CAST(price AS float) ELSE CAST (-price AS FLOAT) END
)
FROM MyEntity;

答案 1 :(得分:0)

我不确定是否支持其他内容,但通常需要设置并指向 别名 entity

因此,请尝试使用这些小更改进行查询(使用别名tcede):

"UPDATE TestCaseExecutionDetailsEntity tcede " +
    " SET tcede.status = " +
    " CASE WHEN (tcede.runOrder < :runOrder) THEN :completedStatus " +
    "      WHEN (tcede.runOrder = :runOrder) THEN :failedStatus " +
    "      WHEN (tcede.runOrder > :runOrder) THEN :abortedStatus " +
    " END " +
    " WHERE tcede.testExecutionJobId = :jobId")