休眠保存/检索日期减去一天,如果应用程序使用MySQL以外的其他时区

2022-09-02 13:22:56

我有一个应用程序在MACHINE_A的tomcat上启动,时区为GMT + 3。

我使用MACHINE_B与时区UTC启动的远程MySQL服务器。

我们使用 spring-data-jpa 来实现持久性。

作为问题的一个例子,我将展示存储库:

public interface MyRepository extends JpaRepository<MyInstance, Long> {
    Optional<MyInstance> findByDate(LocalDate localDate);
}

如果我传递 localDate for ,我会得到日期为(前一天)的实体2018-09-062018-09-05

在我看到的日志中:

2018-09-06 18:17:27.783 TRACE 13676 --- [nio-8080-exec-3] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [DATE] - [2018-09-06]

我在谷歌上搜索了这个问题,发现了几篇内容相同的文章(例如 https://moelholm.com/2016/11/09/spring-boot-controlling-timezones-with-hibernate/)

所以,我有以下几点:application.yml

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/MYDB?useUnicode=true&characterEncoding=utf8&useSSL=false&useLegacyDatetimeCode=false&serverTimezone=UTC
    username: root
    password: *****
  jpa:
    hibernate:
      naming:
        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
    properties:
      hibernate:
        show_sql: true
        use_sql_comments: true
        format_sql: true
        type: trace
        jdbc:
          time_zone: UTC

但这无济于事。

我们使用以下连接器:

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.12</version>
</dependency>

如何解决我的问题?

附言

我试图用相同的时区运行这两个应用程序。在这种情况下,一切按预期工作。

附言 2

我尝试使用MySQL驱动程序6.0.6版本,但它没有改变任何东西。


答案 1

如果你在Java中使用,你应该在MySQL中使用一列。这样问题就会得到解决。LocalDateDATE

如果使用 ,请尝试在 Spring Boot 中按如下方式设置属性:LocalDateTime

spring.jpa.properties.hibernate.jdbc.time_zone=UTC

要查看其运行情况,您可以在我的高性能Java Persistence GitHub存储库中找到一个测试用例,该示例演示了此设置如何与MySQL配合使用。


答案 2

在使用 为应用程序创建一些集成测试时,我遇到了类似的问题。我在这里使用的数据库是 。spring-boothibernatepostgreSQL

正如另一个答案正确指出的那样,您可以像discribed一样设置属性。没关系,这并没有解决我的问题,所以我不得不在我的应用程序主类中借助以下内容设置默认时区:hibernate.jdbc.time_zone=UTCJVMspring-boot

@PostConstruct
public void init(){
    TimeZone.setDefault(TimeZone.getTimeZone("UTC"));   // It will set UTC timezone
    System.out.println("Spring boot application running in UTC timezone :"+new Date());   // It will print UTC timezone
}

这也应该解决您的问题。您可以在此处收集更多信息。

原因

我猜你的问题(检索日期 - 1天)来自你的特定设置。如果您的应用程序在 UTC 中运行,并在 GMT+3 中从数据库请求时间戳,则会在较早的日期解析,因为应用程序上下文(并在此处负责)比 UTC 中的数据库上下文晚 3 小时。简单示例:JVMHibernate

2018-12-02 00:00:00- 3小时=2018-12-01 21:00:00

由于您只关注日期:- 3小时=2018-12-022018-12-01


推荐