使用 between 和 Instant 的 JPA 查询不起作用

Posted

技术标签:

【中文标题】使用 between 和 Instant 的 JPA 查询不起作用【英文标题】:JPA Query using between and Instant not working 【发布时间】:2021-10-05 19:04:18 【问题描述】:

我正在尝试进行查询以检索在两个日期之间创建的一些数据(表示为即时)。

下面是我正在使用的实体的摘录:

@Entity
public class HistoricalData 
@Id
@GeneratedValue
private Long id;

@Column
private String name;

@CreationTimestamp
private Instant timestamp;

@Column
private Double price;


以及我为检索两个 Instant 之间的数据而编写的查询;

@Query("select h from HistoricalData h where h.timestamp between :timestampStart and :timestampEnd and upper(name) = upper(:name)")
List<HistoricalData> findHistoricalDataBetween(@NonNull Instant timestampStart, @NonNull Instant timestampEnd, @NonNull String name);

产生这个 SQL 查询:

select historical0_.id as id1_5_, historical0_.price as price2_5_, historical0_.timestamp as timestam3_5_ from historical_data historical0_ where (historical0_.timestamp between ? and ?) and upper(historical0_.name)=upper(?)

我还写了“hibernate JPA”查询只是为了尝试但没有成功:

List<HistoricalData> findHistoricalDataByTimestampAfterAndTimestampBeforeAndName(@NonNull Instant timestampStart, @NonNull Instant timestampEnd, @NonNull String name);

请记住,以上所有查询都能正确编译并且不会抛出任何异常,它们只是从数据库中检索不到任何内容

我使用的数据库是 MariaDB 的最新版本,连接器版本是 2.7.2 我使用的 SpringBoot 版本也是 2.5.3

这是来自表定义的 DDL(从 Hibernate 自动生成):

create table historical_data
(
id        bigint   not null primary key,
price     double   null,
timestamp datetime not null,
name      varchar  not null
);

这是时间戳在数据库中的样子:

即使这两个 Instant 之间的记录存在于数据库中,我仍然没有从查询中得到任何结果。

【问题讨论】:

您是否尝试过通过启用查询日志来调试应用程序? 是的,我会在问题正文中附上来自 show-sql 的查询 你是否在 JDBC URL 中设置了时区? 不,我认为它是“可选的” 【参考方案1】:

看起来原因是时区。 mysql 驱动程序使用不正确的时区转换,使用默认本地时区代替连接时区(反之亦然)。

只需在 MySQL 驱动程序中调试此查询即可获得乐趣并弄清楚会发生什么。

您可以向数据库 URL 添加参数,以查看为准备语句传递了哪些实际值

jdbc:mysql://<DATABASE_URL>?logger=com.mysql.cj.log.Slf4JLogger&profileSQL=true

【讨论】:

以上是关于使用 between 和 Instant 的 JPA 查询不起作用的主要内容,如果未能解决你的问题,请参考以下文章

java8时间搓计算代码运行时间

The relationship between Sonarcube coverage and co

Oracle Instant Client的安装和使用

在 Spring Boot 和 ElasticSearch 中使用 Instant、LocalDateTime 和 ZonedDateTime

使用 JOOQ 在 java.sql.Timestamp 和 java.time.Instant 之间转换时遇到问题

Java 8 – 使用 TimeZone 从 LocalDateTime 创建 Instant [重复]