我想在给定的时间跨度内显示包含已处理对象数量(以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语法来表达它?
答案 0 :(得分:2)
首先,您需要一种JPA方法来计算相应单元中startDate
和pageDate
之间的差异,这有点难以制定,因为它非常依赖数据库。最后,您将需要一些自定义函数或编写非常复杂的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)