【问题标题】:Spring/Hibernate Date is one day earlier春季/休眠日期提前一天
【发布时间】:2020-06-15 08:11:55
【问题描述】:

@Entity
@Table(name="friend")
public class Friend {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="id")
    private int id;

    @Column(name="name")
    private String name;

    @Column(name="birthday")
    private Date birthday;

    public Date getBirthday() {
        System.out.println("getter" + this.birthday);
        return this.birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

我在这里使用java.sql.Date 将生日插入我的 MySQL 数据库。对于 setter,我使用表单标签和模型属性从 jsp 页面以 yyyy-MM-dd 的形式将日期作为字符串获取。设置后,我检查了我的 db 表,日期与预期一致,但是当我调用 getter 时,日期提前了一天(例如,如果我的 db 中有 2000-06-20,则 getter 返回 2000-06-19 )。

【问题讨论】:

  • 很有可能时区是问题所在,System.out.println 中记录的内容与客户端中呈现的本地日期时间不同。有 3 个可能的时区在起作用:MySQL 服务器。运行 Java 的服务器和呈现日期的客户端。通常服务器(数据库和应用程序服务器)采用 UTC。你可以好好阅读 Joda Time 图书馆。
  • @GregHNZ 是对的,但您不必再使用 JodaTime,因为 Java 8 有 Java DateTime API,您可以使用 LocalDate 而不是 java.sql.Date。但这并不能解决你的问题。
  • 这个问题很可能是"date goes back one day"的重复问题
  • 这能回答你的问题吗? Getting the date goes back one day

标签: java spring hibernate date


【解决方案1】:

错误的数据类型

切勿使用 java.util.Datejava.sql.Date 类。这些类设计得很糟糕,几年前就被 JSR 310 中定义的现代 java.time 类所取代。

顺便说一句,永远不要编写隐式依赖于某个默认时区的代码。这使您作为程序员无法控制您的结果。

LocalDate

要仅表示日期、不带时间、不带时区上下文或与 UTC 的偏移量,请使用 LocalDate

LocalDate localDate = LocalDate.parse( "2000-06-20" ) ;  // Parses standard ISO 8601 format by default.

与您的数据库交换 LocalDate 对象

在类似于 SQL 标准类型DATE 的类型的数据库列中存储仅日期值。请注意,各种数据库在日期时间处理和命名方面差异很大,因此请仔细研究您的文档。特别是在 MySQL 8 中,使用its DATE type

写入数据库。

myPreparedStatement.setObject( … , localDate );

从数据库中检索。

LocalDate localDate = myResultSet.getObject( … , LocalDate.class ) ;

如果您采用这种方法,默认时区将无关紧要。你的结果将是一致的。

Hibernate 和 JPA 支持 java.time

至于您对 Hibernate 的使用,HibernateJPA 都在几年前更新以支持 java.time。确保您的 JDBC driver 符合 JDBC 4.2 或更高版本。

搜索:Hibernate & java.timeJPA & java.time



关于java.time

java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.DateCalendarSimpleDateFormat

要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310

Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。

您可以直接与您的数据库交换 java.time 对象。使用符合JDBC 4.2 或更高版本的JDBC driver。不需要字符串,不需要java.sql.* 类。 Hibernate 5 和 JPA 2.2 支持 java.time

从哪里获得 java.time 类?

【讨论】:

    【解决方案2】:

    我的 jdbc url 末尾有 serverTimezone=UTC,删除它似乎解决了问题。我的数据库服务器和我的 Tomcat 服务器似乎正在使用我的本地时区。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-09-23
      • 2013-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-01
      • 2016-12-14
      相关资源
      最近更新 更多