如何在JPA / Hibernate中使用聚合函数调用SQL查询

时间:2013-03-11 18:20:16

标签: java sql hibernate jpa

是否可以在JPA / Hibernate中运行如下所示的查询?

select v.country,
v.site,
    SUM(case when s.id = 1 then 1 else 0 end) as Total_SuspectedViolations,
    SUM(case when s.id = 2 then 1 else 0 end) as Total_ConfirmedViolations,
    SUM(case when s.id = 3 then 1 else 0 end) as Total_ConfirmedNoViolations,
    SUM(case when s.id = 4 then 1 else 0 end) as Total_NotDetermined,
    COUNT(*) Total
from violations v
inner join status s
    on v.status_id = s.id
group by v.country, v.site

select v.country,
v.site,
    SUM(case when v.status_id = 1 then 1 else 0 end) as Total_SuspectedViolations,
    SUM(case when v.status_id = 2 then 1 else 0 end) as Total_ConfirmedViolations,
    SUM(case when v.status_id = 3 then 1 else 0 end) as Total_ConfirmedNoViolations,
    SUM(case when v.status_id = 4 then 1 else 0 end) as Total_NotDetermined,
    COUNT(*) Total
from violations v
group by v.country, v.site

这适用于Oracle DB,但当我使用JPA / Hibernate时,我得到了:

ERROR [PARSER] line 1:311: unexpected token: total
ERROR [PARSER] line 1:375: unexpected token: ON

我在问,因为我需要根据一个表“Violations”

中的数据实现一些简单的统计数据

以下是我的想法:

我需要连接两个表并从第二个表中计算出现一些值以实现像统计表一样的效果,它将包含列:

结果表:

  • country varchar(20),
  • site varchar(20),
  • susp_violation long,
  • confirmed_violation long,
  • confirmed_no_violation long,
  • not_determined long,
  • 总长

我的结果表需要有前两列(contry和site)来自第一个表“Violations”和接下来的5个列,它们将包含每个可能的id值中“Violations”中出现的status_id数量(count)状态表。

所以,我有两个表:违规和状态。

违反:

  • id long,
  • country varchar(20),
  • site varchar(20),
  • status_id long,< - 这是状态表中的状态ID。
  • ...在这种情况下不重要的其他列

状态:

  • id long,
  • 状态很长 列“status”具有值(1-4),它们映射到字符串值:可疑违规(1),确认违规(2),确认无违规(3),未确定(4)

我的联接结果是要有一个应该包含列的表:

  • 来自违规表:“国家”和“网站”
  • 来自状态表:“可疑违规”,“确认违规”,“确认无违规”,“未确定”,“总计”(此列为违规表中出现的计数器)。

更新:据我所知,现在不需要使用join,查询只能在一个表上运行。

你能否告诉我在JPA / Hibernate中这样做的正确方法是什么?

2 个答案:

答案 0 :(得分:0)

你必须使用

session.createSQLQuery 

并可以使用以下方法将sql结果转换为所需的bean

query.setResultTransformer(Transformers.aliasToBean(YourBean.class))

或您可以使用Projections

答案 1 :(得分:0)

感谢您的建议同时我已经用这种方式解决了它:

List<ViolationSummaryDTO> result = em.createQuery(
                "SELECT new ViolationSummaryDTO(v.counName, v.siteNumber," +
                    "sum(case when v.pvClStati.clstId = 1 then 1 else 0 end) as suspectedViolation," +
                    "sum(case when v.pvClStati.clstId = 2 then 1 else 0 end) as confirmedViolation," +
                    "sum(case when v.pvClStati.clstId = 3 then 1 else 0 end) as confirmedNoViolation," +
                    "sum(case when v.pvClStati.clstId = 0 then 1 else 0 end) as notDetermined," +
                    "COUNT(*) as total)" +
                " FROM Violation v" +
                " WHERE v.trial.id = " + trialId +
                " GROUP BY v.counName, v.siteNumber", ViolationSummaryDTO.class).getResultList();

结果是hibernate在 SELECT new 语句中创建的对象列表。