【发布时间】:2021-08-03 17:16:11
【问题描述】:
我在 PostgreSQL 13 上使用带有 TimescaleDB 扩展的 Spring Data JPA(下面带有 Hibernate,JPA 2.1),并希望使用 time_bucket 函数。这需要bucket_width 这是一个INTERVAL 和time 这是数据的TIMESTAMP 列。
我想把它放在 Spring Data Repository 中,并希望使用 JPQL @Query 将数据提取到一个投影中,该投影表示返回的时间段的聚合计数、平均值等。我不想使用原生查询,因为我想加入其他一些表,并自动填充它们的实体。
我将time_bucket 函数注册到我正在扩展的PostgisPG95Dialect,如下所示:
public class CustomPostgresqlDialect extends PostgisPG95Dialect {
public CustomPostgresqlDialect() {
super();
this.registerFunction("time_bucket", new StandardSQLFunction("time_bucket", new OffsetDateTimeType()));
}
}
如果bucket_width 是硬编码的,那么所有这些都可以正常工作。但我希望bucket_width 成为查询方法的参数。
以下工作正常:
@Query("select sys as system, "
+ "function('time_bucket', '10 mins', vt.ts) as startTime, "
+ "count(vt) as total, avg(vt.speed) as avgSpeed "
+ "from Data vt "
+ "JOIN vt.system sys "
+ "where sys.sysId = :sysId and "
+ "function('time_bucket', '10 mins', vt.ts) between :from and :to "
+ "group by system, startTime "
+ "order by startTime")
List<SummaryAggregate> getSummaryData(
@Param("sysId") String sysId,
@Param("from") OffsetDateTime from,
@Param("to") OffsetDateTime to);
但是当我尝试参数化间隔时,我无法让它工作。我尝试将间隔作为字符串传递,因为这是硬编码版本中的写入方式:
@Query("select sys as system, "
+ "function('time_bucket', :grouping, vt.ts) as startTime, "
+ "count(vt) as total, avg(vt.speed) as avgSpeed "
+ "from Data vt "
+ "JOIN vt.system sys "
+ "where sys.sysId = :sysId and "
+ "function('time_bucket', :grouping, vt.ts) between :from and :to "
+ "group by system, startTime "
+ "order by startTime")
List<SummaryAggregate> getSummaryData(
@Param("sysId") String sysId,
@Param("from") OffsetDateTime from,
@Param("to") OffsetDateTime to,
@Param("grouping") String grouping);
其中grouping 传递了一个类似10 mins 的值。
但为此我收到此错误:
SQL Error: 0, SQLState: 42883
ERROR: function time_bucket(character varying, timestamp with time zone) does not exist
Hint: No function matches the given name and argument types. You might need to add explicit type casts.
Position: 61
然后我尝试将其更改为Duration,因为Hibernate translates Duration to PostgreSQL Interval types
@Query("select sys as system, "
+ "function('time_bucket', :grouping, vt.ts) as startTime, "
+ "count(vt) as total, avg(vt.speed) as avgSpeed "
+ "from Data vt "
+ "JOIN vt.system sys "
+ "where sys.sysId = :sysId and "
+ "function('time_bucket', :grouping, vt.ts) between :from and :to "
+ "group by system, startTime "
+ "order by startTime")
List<SummaryAggregate> getSummaryData(
@Param("sysId") String sysId,
@Param("from") OffsetDateTime from,
@Param("to") OffsetDateTime to,
@Param("grouping") Duration grouping);
但我仍然遇到同样的错误,这一次它认为 Duration 是 bigint 而不是 Interval。
SQL Error: 0, SQLState: 42883
ERROR: function time_bucket(bigint, timestamp with time zone) does not exist
Hint: No function matches the given name and argument types. You might need to add explicit type casts.
Position: 61
有没有办法使用 JPQL 参数化 Interval?
【问题讨论】:
标签: postgresql hibernate jpql jpa-2.1 timescaledb