JPA 查询验证在子选择时失败,即使它在控制台中工作

JPA query validation fails at subselect even though it is working in console

情况:

我得到了以下 jpa 查询,它在 IntelliJ jpa-ql 控制台中完美运行。我已将其添加为图片,以便可以看到突出显示的代码以及实际错误:

select 
    run1.someAttribute1 AS someAttribute1, 
    run1.someAttribute2 AS someAttribute2, 
    run1.someAttribute3 AS someAttribute3, 
    (select
        sum(function('timestampdiff', SECOND, run2.runStartTime, run2.runEndTime)) 
        from runTable AS run2 
        where run2.anotherAttribute1 = run1.anotherAttribute1 
        and run2.anotherAttribute2 = run1.someAttribute2 
        and run2.anotherAttribute3 = run1.someAttribute3
    ) AS runtime, 
    sum(
        case when type(event) = SomeEvent and event.someType = '...' then 1   
        else 0 end
    ) AS numberOfSomething1,
    sum(
        case when type(event) = SomeEvent and event.someType = '...' then 1     
        else 0 end
    ) AS numberOfSomething2, 
    sum(
        case when type(event) = SomeEvent and event.someType = '...' then 1 
        else 0 end
    ) AS numberOfSomething3, 
    sum(
        case when type(event) = SomeEvent and event.someType = '...' then 1 
        else 0 end
    ) AS numberOfSomething4, 
    sum(
        case when type(event) = SomeEvent2 then 1 
        else 0 end
    ) AS numberOfSomething5from runTable AS run1 
left join run1.events AS event 
group by someAttribute1, someAttribute2, someAttribute3 
order by 
    max(function('right', function('left', someAttribute1, 8), 3)) desc,    
    someAttribute2 desc, 
    someAttribute3 desc

JPA Query with subselect validation error

如果在 jpa-ql 控制台中 运行 returns 结果如下:

Right result with sub select

第三列是以秒为单位的运行时间,如果用 subselect 查询完成的话,这是正确的。如果我重构 subselect 以使用 run1 别名它 returns 错误的结果。我认为分组确实已经包含正确的运行时间,但显然我错了:

select 
    run1.someAttribute1 AS someAttribute1, 
    run1.someAttribute2 AS someAttribute2, 
    run1.someAttribute3 AS someAttribute3, 
    sum(
       function('timestampdiff', SECOND, run1.runStartTime, run1.runEndTime)
    ) AS runtime, 
    sum(case when type(event) = SomeEvent and event.someType = '...' then 1 else 0 end) AS numberOfSomething1,
    sum(case when type(event) = SomeEvent and event.someType = '...' then 1 else 0 end) AS numberOfSomething2, 
    sum(case when type(event) = SomeEvent and event.someType = '...' then 1 else 0 end) AS numberOfSomething3, 
    sum(case when type(event) = SomeEvent and event.someType = '...' then 1 else 0 end) AS numberOfSomething4, 
    sum(case when type(event) = SomeEvent2 then 1 else 0 end) AS numberOfSomething5from runTable AS run1 
left join run1.events AS event 
group by someAttribute1, someAttribute2, someAttribute3 
order by max(function('right', function('left', someAttribute1, 8), 3)) desc,
    someAttribute2 desc, 
    someAttribute3 desc

Wrong result with alias from the FROM clause

问题

主要区别在于,第一个 jpa 查询在启动 spring 引导应用程序时抛出错误,而重构的查询则不会:

Caused by: java.lang.IllegalArgumentException: Validation failed for query for method public abstract java.util.List someClass.someMethod()
at org.springframework.data.jpa.repository.query.SimpleJpaQuery.validateQuery(SimpleJpaQuery.java:92) ~[spring-data-jpa-1.11.8.RELEASE.jar:?]
at org.springframework.data.jpa.repository.query.SimpleJpaQuery.<init>(SimpleJpaQuery.java:62) ~[spring-data-jpa-1.11.8.RELEASE.jar:?]
at org.springframework.data.jpa.repository.query.JpaQueryFactory.fromMethodWithQueryString(JpaQueryFactory.java:72) ~[spring-data-jpa-1.11.8.RELEASE.jar:?]
at org.springframework.data.jpa.repository.query.JpaQueryFactory.fromQueryAnnotation(JpaQueryFactory.java:53) ~[spring-data-jpa-1.11.8.RELEASE.jar:?]
at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$DeclaredQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:144) ~[spring-data-jpa-1.11.8.RELEASE.jar:?]
at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateIfNotFoundQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:211) ~[spring-data-jpa-1.11.8.RELEASE.jar:?]
at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$AbstractQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:77) ~[spring-data-jpa-1.11.8.RELEASE.jar:?]
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.<init>(RepositoryFactorySupport.java:436) ~[spring-data-commons-1.13.8.RELEASE.jar:?]
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:221) ~[spring-data-commons-1.13.8.RELEASE.jar:?]
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.initAndReturn(RepositoryFactoryBeanSupport.java:277) ~[spring-data-commons-1.13.8.RELEASE.jar:?]
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:263) ~[spring-data-commons-1.13.8.RELEASE.jar:?]
at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:101) ~[spring-data-jpa-1.11.8.RELEASE.jar:?]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1687) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1624) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1138) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
... 17 more

似乎 spring 数据无法处理 select 子句中逗号后面的左括号(请参阅 1),即使实际查询确实有效。

问题

有什么方法可以解决这个问题或重写 subselect 查询吗?

使用 spring-数据版本 1.11.8 进行查询验证

我不知道你在控制台中执行了什么,但你发布的查询都不是,一旦你像我一样格式化它们就很明显了。

在这两种情况下,left join之前的from前面都少了一个space。

此外,我认为子选择应该以关键字 select 开头。