java - JPA UTC 时区查询谓词问题
问题描述
我在将 Spring Boot Starter Parent 从 2.0.9.RELEASE 升级到 2.3.3.RELEASE 时遇到问题。更具体地说,我将问题追溯到从 2.0.9.RELEASE 迁移到 2.1.0.RELEASE。在 2.1.0.RELEASE 之前,我们所有的标准构建器谓词都像下面的例子一样进行相等比较。随着升级到 2.1.0.RELEASE,我们不再能够进行 equals 比较,因为没有返回匹配的行。
Predicate foreverDatePredicate = criteriaBuilder.equal(root.get("deactivatedAt"), LocalDateTime.of(9999, Month.DECEMBER, 31, 0, 0, 0))
看来这两个 Spring Boot 版本从 Hibernate Core 5.2.18.FINAL 到 5.3.7.FINAL,可能还有 JPA 2.1 到 2.2。我不确定这些版本更改是否与以下问题有关。
由于本地时区 (PST) 与存储在数据库中的时区 (UTC) 之间的时区不匹配,问题似乎正在发生。在我的 sql 编辑器中,我能够验证休眠查询是否正常工作,并在 where 子句中未提供时区时返回适当的行。我们所有的日期时间列都以 UTC 时间存储在我们的 MySQL 数据库中。我尝试在 application.properties 和我们的 Hibernate JPA 属性中使用以下时区相关属性,但两者似乎都不起作用或被完全忽略:
# application.properties
spring.jpa.properties.hibernate.jdbc.time_zone=UTC
# Used in jpaProperties property under entityManagerFactory
hibernate.jdbc.time_zone=UTC
正如其他一些线程所建议的那样,我可以将 JVM 时区设置为 UTC,并且在尝试后它可以工作;但是,我宁愿避免这样做,因为对于应该能够在更细粒度级别解决的问题来说,这似乎是一个影响深远的修复:
@PostConstruct
public void started() {
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
}
我最终将负责映射到 MySQL 日期时间列的 Hibernate 实体类型从 LocalDateTime 转换为 OffsetDateTime,如下所示。默认情况下,OffsetDateTime 以 UTC 时间存储带有时区的完整时间戳,这已经解决了问题,我们的 datetime equals 谓词再次起作用,但这引起了重大的重构问题。
从改变
@MappedSuperclass
public class BitemporalEntity implements Serializable {
private static final long serialVersionUID = 2966895098986638738L;
@Column(name = "deactivated_at")
protected LocalDateTime deactivatedAt;
至
@MappedSuperclass
public class BitemporalEntity implements Serializable {
private static final long serialVersionUID = 2966895098986638738L;
@Column(name = "deactivated_at")
protected OffsetDateTime deactivatedAt;
我只是想知道我是否在这里遗漏了什么。使用 OffsetDateTime 而不是 LocalDateTime 是解决问题的好方法还是有其他方法?
解决方案
推荐阅读
- typescript - 使用 combineReducers 遇到已知错误,无法解决包依赖关系
- javascript - 为什么我的反应组件没有更新图片库?
- django - 获取具有唯一正则表达式命中数和唯一正则表达式命中的数据的正则表达式
- java - LEFT JOIN SUBQUERY 中的 Blaze-Persistence GROUP BY 与根查询中的 COALESCE
- javascript - vuejs:改变宽度每个循环基于 vuejs 中数组的 2 个变量
- python - Seaborn 在多次调用函数时保存相同的数字
- linux - Linux 找到 Bash/Bourne 文件,然后添加 .sh
- google-cloud-platform - 如何从云中执行的 Dataflow 管道中的 Google Drive 文件夹中读取数据?
- python - 将文件写入 Python 三
- android - 使用 uri i/o 错误上传多种类型的文件以解析数据库