JPA2.2 + SELECT 中的子查询用于聚合
JPA2.2 + Subquery in SELECT for aggregation
我正在这里开发 Spring Boot 2.3。1.RELEASE 应用程序,它带来了 Hibernate 5.4 + JPA 2.2。
数据库(此处缩写):
Table 1 (sri):
id | fund_id
1 | 20
2 | 21
3 | 22
Table 2(参考):
id | SECURITY_ID | FUND_PROPORTION | value
100 | 1 | 0.2 | 70
101 | 1 | 0.1 | 20
102 | 1 | 0.5 | 60
103 | 2 | 0.1 | 95
104 | 2 | 0.1 | 23
105 | 2 | 0.2 | 48
106 | 3 | 0.4 | 65
107 | 3 | 0.5 | 16
108 | 3 | 0.2 | 32
...实际值不相关 - 只是为了展示我如何获得这些值。
我需要select数据库中的值,但由于结果量很大,我希望数据库进行计算。这就是为什么我设置了以下查询(此处 post 的缩写)查询,它在数据库上使用纯 SQL 完美运行:
select
RATING,
SUM(FUND_PROPORTION),
COUNT(FUND_PROPORTION)
from (
SELECT
ref.FUND_PROPORTION as FUND_PROPORTION ,
Case
when ref.value <= 100 AND ref.value > 90 then 'A'
when ref.value <= 90 AND ref.value > 75 then 'B'
when ref.value <= 75 AND ref.value > 50 then 'C'
when ref.value <= 50 AND ref.value > 25 then 'D'
when ref.value <= 25 AND ref.value > 10 then 'E'
when ref.value <= 10 then 'F'
END AS RATING
FROM
table1 sri,
table2 ref
WHERE
sri.id = ref.SECURITY_ID
AND sri.fund_id = SOME ID
GROUP BY FUND_PROPORTION, RATING
) as t1
group by RATING;
这 return 是预期的结果:
RATING SUM(FUND_PROPORTION) COUNT(FUND_PROPORTION)
B 0.32 1
C 0.28 2
D 0.14 5
E 0.03 7
F 0.01 8
...基本上我需要有一组所有 FUND_PROPORTIONS 和评级,它通过根据它的值(由案例语句定义)给它一个名称来标识该集合。然后 运行 在该值上 count/sum 和 return 它。
我的问题:我在 Java 中 运行 无法得到它。启动存储库(JpaRepository 或 JpaCustomRepository)后,它会抱怨“额外的”“(”——这是子查询的开始。
似乎我不能在(主)查询的 SELECT 部分有子查询。
我试过使用本机查询,但由于我们使用的是 UUID,驱动程序尝试转换值 ti byte[] 但失败了(惊奇,惊奇)。我试过使用 CriteriaAPI,但我能找到的所有示例都是关于在 WHERE 部分中使用子查询的 - 这对我没有帮助。
当然,我可以 运行 运行 只是子查询并直接在 Java 中组合这些值,但这意味着将大量数据加载到应用程序中 - 这是这不是我想要发生的(结果来自一个小型测试数据库,产品在数量上看起来会有所不同)。
现在,我绝对愿意将上面的查询转换为其他内容,例如加入。但我不知道如何重写查询。
有什么想法吗? JPA(最喜欢的)、Criteria Api 或完全重写 - 构成这件事的所有内容+运行ning 都可以。
非常感谢。
刀
PS:周末我会在山上,所以在 7 月 20 日星期一之前我身边没有 read/response。
在注释中使用 nativeQuery
属性以使用 SQL
@Query(
value = "SELECT ...",
nativeQuery = true
)
Lukas Eder/User - Upvote don't say Thanks感谢您的支持。使用 nativeQuery 属性并不是完整的答案,但最终让我找到了以下解决方案:
在这里使用 nativeQuery = true 不起作用,因为您基本上失去了 Hibernate 对定义响应对象的支持(抱歉,这不是我最初请求的一部分)。
所以现在我切换到 CustomRepository,添加 META-INF/orm.xml,定义响应对象:
<entity-mappings version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence/orm
http://xmlns.jcp.org/xml/ns/persistence/orm_2_1.xsd">
<sql-result-set-mapping name="DistributionSearchResult">
<constructor-result target-class="searchresult.DistributionSearchResult">
<column name="RATING" class="java.lang.String"/>
<column name="sum" class="java.math.BigDecimal"/>
<column name="count" class="java.lang.Long"/>
</constructor-result>
</sql-result-set-mapping>
创建nativeQuery时引用了如下定义:
final String queryString = " SELECT " +
" RATING, " +
" SUM(FUND_PROPORTION) as sum, " +
" COUNT(FUND_PROPORTION) as count" +
" FROM ( " +
" SELECT " +
" ref.fund_Proportion as FUND_PROPORTION, " +
" CASE " +
" when ref.value <= 100 AND ref.value > 90 then 'A' " +
" when ref.value <= 90 AND ref.value > 75 then 'B' " +
" when ref.value <= 75 AND ref.value > 50 then 'C' " +
" when ref.value <= 50 AND ref.value > 25 then 'D' " +
" when ref.value <= 25 AND ref.value > 10 then 'E' " +
" when ref.value <= 10 then 'F' " +
" END AS RATING " +
" FROM " +
" Security_Provider_Info spi, " +
" SCORE_ESG_REFINITIV_SEC_PROV ref " +
" WHERE " +
" sri.id = ref.SECURITY_ID " +
" AND sri.fund_id = :SOME_ID " +
" ) as t1 " +
" GROUP BY RATING ";
/* set Parameter */
final JpaQueryParameters parameters = new JpaQueryParameters();
parameters.setParameter("SOME_ID", 123);
/* see orm.xml for definition of DistributionSearchResult */
final Query query = entityManager.createNativeQuery(queryString, "DistributionSearchResult");
parameters.addParameters(query);
这样,结果按要求分组并被推送到我的 DistributionSearchResult 类型的结果对象中。
非常感谢:)
刀
我正在这里开发 Spring Boot 2.3。1.RELEASE 应用程序,它带来了 Hibernate 5.4 + JPA 2.2。
数据库(此处缩写): Table 1 (sri):
id | fund_id
1 | 20
2 | 21
3 | 22
Table 2(参考):
id | SECURITY_ID | FUND_PROPORTION | value
100 | 1 | 0.2 | 70
101 | 1 | 0.1 | 20
102 | 1 | 0.5 | 60
103 | 2 | 0.1 | 95
104 | 2 | 0.1 | 23
105 | 2 | 0.2 | 48
106 | 3 | 0.4 | 65
107 | 3 | 0.5 | 16
108 | 3 | 0.2 | 32
...实际值不相关 - 只是为了展示我如何获得这些值。
我需要select数据库中的值,但由于结果量很大,我希望数据库进行计算。这就是为什么我设置了以下查询(此处 post 的缩写)查询,它在数据库上使用纯 SQL 完美运行:
select
RATING,
SUM(FUND_PROPORTION),
COUNT(FUND_PROPORTION)
from (
SELECT
ref.FUND_PROPORTION as FUND_PROPORTION ,
Case
when ref.value <= 100 AND ref.value > 90 then 'A'
when ref.value <= 90 AND ref.value > 75 then 'B'
when ref.value <= 75 AND ref.value > 50 then 'C'
when ref.value <= 50 AND ref.value > 25 then 'D'
when ref.value <= 25 AND ref.value > 10 then 'E'
when ref.value <= 10 then 'F'
END AS RATING
FROM
table1 sri,
table2 ref
WHERE
sri.id = ref.SECURITY_ID
AND sri.fund_id = SOME ID
GROUP BY FUND_PROPORTION, RATING
) as t1
group by RATING;
这 return 是预期的结果:
RATING SUM(FUND_PROPORTION) COUNT(FUND_PROPORTION)
B 0.32 1
C 0.28 2
D 0.14 5
E 0.03 7
F 0.01 8
...基本上我需要有一组所有 FUND_PROPORTIONS 和评级,它通过根据它的值(由案例语句定义)给它一个名称来标识该集合。然后 运行 在该值上 count/sum 和 return 它。
我的问题:我在 Java 中 运行 无法得到它。启动存储库(JpaRepository 或 JpaCustomRepository)后,它会抱怨“额外的”“(”——这是子查询的开始。 似乎我不能在(主)查询的 SELECT 部分有子查询。
我试过使用本机查询,但由于我们使用的是 UUID,驱动程序尝试转换值 ti byte[] 但失败了(惊奇,惊奇)。我试过使用 CriteriaAPI,但我能找到的所有示例都是关于在 WHERE 部分中使用子查询的 - 这对我没有帮助。
当然,我可以 运行 运行 只是子查询并直接在 Java 中组合这些值,但这意味着将大量数据加载到应用程序中 - 这是这不是我想要发生的(结果来自一个小型测试数据库,产品在数量上看起来会有所不同)。
现在,我绝对愿意将上面的查询转换为其他内容,例如加入。但我不知道如何重写查询。
有什么想法吗? JPA(最喜欢的)、Criteria Api 或完全重写 - 构成这件事的所有内容+运行ning 都可以。
非常感谢。
刀
PS:周末我会在山上,所以在 7 月 20 日星期一之前我身边没有 read/response。
在注释中使用 nativeQuery
属性以使用 SQL
@Query(
value = "SELECT ...",
nativeQuery = true
)
Lukas Eder/User - Upvote don't say Thanks感谢您的支持。使用 nativeQuery 属性并不是完整的答案,但最终让我找到了以下解决方案:
在这里使用 nativeQuery = true 不起作用,因为您基本上失去了 Hibernate 对定义响应对象的支持(抱歉,这不是我最初请求的一部分)。
所以现在我切换到 CustomRepository,添加 META-INF/orm.xml,定义响应对象:
<entity-mappings version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence/orm
http://xmlns.jcp.org/xml/ns/persistence/orm_2_1.xsd">
<sql-result-set-mapping name="DistributionSearchResult">
<constructor-result target-class="searchresult.DistributionSearchResult">
<column name="RATING" class="java.lang.String"/>
<column name="sum" class="java.math.BigDecimal"/>
<column name="count" class="java.lang.Long"/>
</constructor-result>
</sql-result-set-mapping>
创建nativeQuery时引用了如下定义:
final String queryString = " SELECT " +
" RATING, " +
" SUM(FUND_PROPORTION) as sum, " +
" COUNT(FUND_PROPORTION) as count" +
" FROM ( " +
" SELECT " +
" ref.fund_Proportion as FUND_PROPORTION, " +
" CASE " +
" when ref.value <= 100 AND ref.value > 90 then 'A' " +
" when ref.value <= 90 AND ref.value > 75 then 'B' " +
" when ref.value <= 75 AND ref.value > 50 then 'C' " +
" when ref.value <= 50 AND ref.value > 25 then 'D' " +
" when ref.value <= 25 AND ref.value > 10 then 'E' " +
" when ref.value <= 10 then 'F' " +
" END AS RATING " +
" FROM " +
" Security_Provider_Info spi, " +
" SCORE_ESG_REFINITIV_SEC_PROV ref " +
" WHERE " +
" sri.id = ref.SECURITY_ID " +
" AND sri.fund_id = :SOME_ID " +
" ) as t1 " +
" GROUP BY RATING ";
/* set Parameter */
final JpaQueryParameters parameters = new JpaQueryParameters();
parameters.setParameter("SOME_ID", 123);
/* see orm.xml for definition of DistributionSearchResult */
final Query query = entityManager.createNativeQuery(queryString, "DistributionSearchResult");
parameters.addParameters(query);
这样,结果按要求分组并被推送到我的 DistributionSearchResult 类型的结果对象中。
非常感谢:)
刀