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
开头。
情况:
我得到了以下 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
开头。