LocalDate MySQL 持久性返回之前的日期

tjh*_*s66 5 mysql spring hibernate jpa-2.0 java-8

我已经在 StackOverflow 上多次看到这个问题,而且大多数情况下都是使用 Spring Boot 配置的 Spring Boot 应用程序。我已按照所有步骤进行操作,但仍然存在此问题。如果我不能很快解决这个问题,我将不得不回到旧的 java.util.Date 以便将我的数据保存到数据库中......至少它没有问题。所以,我有一个 Spring 5.1.2.Release 应用程序,带有 Hibernate 5.4.0.Final、hibernate-java8 依赖项和最新的 MySQL Connector 8.0.13。

我从以前的帖子和网络上的其他文章中了解到,如果数据库设置为 UTC,但应用程序在另一个时区运行,在我的情况下为 EST 的 GMT-5,那么这个问题可能会弹出。

所以,这里是技术细节:我的 MySQL 连接看起来像:

hibernate.connection.url=jdbc:mysql://localhost:3306/my_db? 
serverTimezone=UTC&useLegacyDatetimeCode=false&useTimezone=true
Run Code Online (Sandbox Code Playgroud)

连接字符串,在 applicationContext.xml 中使用:

<bean id="dataSource"
    class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName">
        <value>${hibernate.connection.driver.class}</value>
    </property>
    <property name="url">
        <value>${hibernate.connection.url}</value>
    </property>
    <property name="username">
        <value>${hibernate.connection.username}</value>
    </property>
    <property name="password">
        <value>${hibernate.connection.password}</value>
    </property>
</bean>
Run Code Online (Sandbox Code Playgroud)

我的 applicationContext.xml 中的 Hibernate 属性如下所示:

<property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">${hibernate.dialect}</prop>
            <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
            <prop key="hibernate.cglib.use_reflection_optimizer">${hibernate.cglib.use_reflection_optimizer}</prop>
            <prop key="useUnicode">true</prop>
            <prop key="useLegacyDatetimeCode">false</prop>
            <prop key="serverTimezone">UTC</prop>
            <prop key="useTimezone">true</prop>
            <prop key="hibernate.jdbc.time_zone">UTC</prop>
        </props>
    </property>
Run Code Online (Sandbox Code Playgroud)

我的 Maven 依赖项是:

    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.13</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>5.4.0.Final</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-java8</artifactId>
        <version>5.4.0.Final</version>
    </dependency>
Run Code Online (Sandbox Code Playgroud)

我的实体代码很简单:

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "transaction_id")
private long txId;

@Column(name = "transaction_date")
private LocalDate txDate;
Run Code Online (Sandbox Code Playgroud)

我将代码保存到数据库中,如下所示:

@Override
public TxEntity create(TxEntity txEntity)
{
    this.sessionFactory.getCurrentSession().save(txEntity);
    this.sessionFactory.getCurrentSession().flush();
    this.sessionFactory.getCurrentSession().refresh(txEntity);
    return txEntity;
}
Run Code Online (Sandbox Code Playgroud)

数据库将“transaction_date”作为 MySQL 中的 DATE 字段。

我的单元测试显示我可以创建一个新记录,并且我已将日期设置如下:

      LocalDate today = LocalDate.now();
Run Code Online (Sandbox Code Playgroud)

我坚持记录,当我测试时:

assertEquals(today, myRecord.getTransactionDate());
Run Code Online (Sandbox Code Playgroud)

这失败了,因为我得到了上一个日期。

我想如果我使用最新版本的 Hibernate 和 Hibernate-java8 就好了,但事实并非如此。我想如果我使用最新的 JPA2.2 会起作用,但事实并非如此。所以,我认为我做的一切都是正确的,但我仍然有一个问题。

所以,如果你有什么需要看的,请告诉我,我可以添加。我认为我做的一切都是正确的,但是如果有什么需要我解决的地方,请告诉我。当然,我自己会继续研究这个。

Raf*_*eco 0

如果您不想修改 Java 项目或连接字符串来解决此问题,您可以直接配置 MySQL 时区。在我的计算机上,JVM 时区是正确的(America/Sao_Paulo),因此将其更改为 UTC 以解决与 MySQL 的冲突是行不通的。

我遇到的问题只是 MySQL 时区配置。因为我在容器上运行 MySQL,所以它得到了错误的默认时区。修复方法是将 传递--default-time-zone=America/Sao_Paulo给 MySQL 容器配置,这解决了这个问题。现在 MySQL 和 JVM 都获得了相同的时区。