如何将对象排序到桶中作为有效的JPQL表达式?

时间:2015-12-03 08:17:14

标签: java hibernate postgresql jpa

我想在给定的时间跨度内显示包含已处理对象数量(以JPA映射)的二维图表。在30分钟的时间内,此数量可以扩展到大约30k个对象。

作为DBMS,我在版本4.2.21中使用PostgreSQL 9.4和JPA 2.0与Hibernate。

目前我正在使用这段代码,以便将金额添加到我的时间"桶"。

 // Get all objects after a given start date
List<MyObject> myObjects= myJPADbService.getMyObjects(Date.from(startDate.atZone
            (ZoneId.systemDefault()).toInstant()), Integer.MAX_VALUE);

for (MyObject information : myObjects) {
        LocalDateTime pageDate = LocalDateTime.ofInstant(Instant.ofEpochMilli(information.getLastSeen().getTime()), ZoneId.systemDefault());          
    long duration;
    if (temporalUnit == ChronoUnit.MINUTES) {
     duration = Duration.between(startDate, pageDate).toMinutes();
    } else if (temporalUnit == ChronoUnit.DAYS) {
     duration = Duration.between(startDate, pageDate).toDays();
    } else {
     duration = Duration.between(startDate, pageDate).toHours();
   }

  pagesPerUnit[(int) (Math.abs(duration))]++;
}

但是,根据用户选择的时间跨度,这段代码可能效率非常低。如果DBMS根据用户选择的时间跨度计算存储桶,则效率可能更高。

如何用适当的JPQL语法来表达它?

1 个答案:

答案 0 :(得分:2)

首先,您需要一种JPA方法来计算相应单元中startDatepageDate之间的差异,这有点难以制定,因为它非常依赖数据库。最后,您将需要一些自定义函数或编写非常复杂的JPQL查询。

计算PostgreSQL中两个日期之间的天数就像执行date_part('day', t2 - t1)一样简单。您需要的时间为date_part('day', t2 - t1) * 24 + date_part('hour', t2 - t1)和分钟date_part('day', t2 - t1) * 24 * 60 + date_part('hour', t2 - t1) * 60 + date_part('minute', t2 - t1)

为了在JPQL中使用这些数据库函数,您可以使用FUNCTION之类的FUNCTION('date_part', 'day', :startDate - pageDate)语法。

最后,您将通过这样的表达式进行分组并按ID进行计数,如下所示

SELECT COUNT(o.id) FROM MyObject o GROUP BY FUNCTION('date_part', 'day', :startDate - o.pageDate)