我的实体有一个java.sql.Timestamp字段:

@Column(name = "expires_at")
private Timestamp expiresAt;

该表还有一个默认列updated_at,该列在插入/更新时动态设置(即,它不是通过JPA设置的):

  updated_at       DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

我以这种方式在持久化实体中设置了expiresAt:

long currTimestamp = Instant.now().getEpochSecond();
LocalDateTime ldt = LocalDateTime.ofInstant(Instant.ofEpochSecond(currTimestamp), ZoneId.of("UTC"));
Timestamp expiresAt = Timestamp.valueOf(ldt);

myEntity.setExpiresAt(expiresAt);

我位于PDT时区.我在本地运行了Spring Boot应用程序,它使用我的Docker Desktop中的MySQL容器. 此查询显示UTC时间,这意味着MySQL容器的时区为UTC:

select now();

但是,当我将实体持久化到表中并执行select时,包含expires_at列的DateTime字符串显示PDT时间.updated_at栏显示UTC时间.

有趣的是,从我的AWS ECS Spring Boot应用程序到AWS RDS MySQL实例的记录都显示为expires_atupdated_at的UTC.

当我将本地JDBC字符串(用于连接到Docker Desktop容器)更新为mysql://localhost:3306/mydbname?connectionTimeZone=UTC时,两者都显示UTC.

有谁能解释一下为什么会发生这种情况?为什么在AWS RDS中,它们都以UTC显示,尽管我在那里没有使用connectionTimeZone标志

推荐答案

updated_at这个数字很容易理解.由于它的值由MySQL定义,因此它始终等于您本地MySQL和AWS RDS中的MySQL时区(UTC).

expires_at更棘手,因为它的值由JDBC驱动程序管理,该驱动程序也有其时区设置.使用时

preparedStatement.setTimestamp(index, timestamp)

默认使用哪个Hibernate 来配置将哪个时间值存储到数据库中,JDBC驱动程序将根据其时区设置进行转换,该时区设置可以由JDBC连接URL中的connectionTimeZone显式定义.否则,它将默认使用JVM时区.因此,假设您在AWS中运行的Spring-Boot应用程序现在已配置为UTC时区.

expires_at的不同情况可以解释如下:

  • 在本地+无connectionTimeZone个配置的JVMJDBC驱动程序中运行默认为➜时区(即,PDT)➜存储在PDT时间
  • 在本地+connectionTimeZone=UTC➜jdbc驱动程序中运行,在协调世界时将其转换为协调世界时➜store
  • 在aws+no connectionTimeZone配置的JVMDBC驱动程序中运行默认为➜时区(即UTC)以UTC时间表示的➜存储

由于MySQL DATETIME不会存储任何时区信息,因此由获取其值的客户端应用程序来定义时区.如果您不想更改它的数据类型,建议您至少将您的JVM和DB调整为相同的时区设置,以防止出现一些奇怪的问题.我猜现在在您的本地设置中,当Hibernate获取其值时,您将遇到updated_at的 timeshift 问题,因为它会将其视为PDT时间,但实际上它是UTC时间.

Java相关问答推荐

Java JAR环境(JRE)是否支持模块?

Java List with all combinations of 8 booleans

Jlink选项&-strie-ative-Commands";的作用是什么?

Java中是否有某种类型的池可以避免重复最近的算术运算?

try 创建一个对象,使用它,然后使用一条语句将其存储为列表

有没有办法让扩展变得多态?

在Java中如何从Executors.newFixedThreadPool(MAX_THREAD_COUNT())迁移到虚拟线程

多重延迟签名

基于接口的投影、原生查询和枚举

如何将Pane的图像快照保存为BMP?

在处理2个映射表时,没有更多的数据可从套接字读取

泛型与泛型问题的完美解决方案?

如何在Java中使用正则表达式拆分字符串

在应用程序运行时更改LookAndFeel

在Spring Boot中使用咖啡因进行缓存-根据输出控制缓存

如何在JSP中从select中获取值并将其放入另一个select

在数组中查找素数时出现逻辑错误

双对象供应商

如何在Java上为循环数组从synchronized迁移到ReentrantLock

如何在 WebSphere Application Server 内的托管线程上运行 BatchEE 作业(job)?