在 java.util.Date 或 java.sql.Date 之间进行选择

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24650186/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 13:45:57  来源:igfitidea点击:

Choosing between java.util.Date or java.sql.Date

javajpaentity

提问by Carlos Goce

Should I use java.util.Date or java.sql.Date?

我应该使用 java.util.Date 还是 java.sql.Date?

I have a VisualFox database and I have retrieved the entities with the IntelliJ Idea wizard using an appropiate jdbc type 4 driver.

我有一个 VisualFox 数据库,并且使用合适的 jdbc 类型 4 驱动程序通过 IntelliJ Idea 向导检索了实体。

The ide (or the driver) has created the date fields as Timestamp. However, the date fields are not timestamps but Date fields, they store year, month and day only.

ide(或驱动程序)已将日期字段创建为时间戳。但是,日期字段不是时间戳而是日期字段,它们仅存储年、月和日。

So I wonder if I should switch to java.util.Date or java.sql.Date. At first glance I thought that java.sql.Date should be the appropiate one, but it has many methods declared as deprecated.

所以我想知道我是否应该切换到 java.util.Date 或 java.sql.Date。乍一看,我认为 java.sql.Date 应该是合适的,但它有许多方法声明为已弃用。

采纳答案by Basil Bourque

tl;dr

tl;博士

Should I use java.util.Date or java.sql.Date?

我应该使用 java.util.Date 还是 java.sql.Date?

Neither.

两者都不。

Both are obsolete as of JDBC4.2 and later. Use java.timeclasses instead.

JDBC4.2 及更高版本开始,两者都已过时。改用java.time类。

  • date-only value
    For a database type akin to SQL-standard DATE, use java.time.LocalDate.
    • LocalDate ld = myResultSet.getObject( … , LocalDate.class ) ;
    • myPreparedStatement.setObject( ld , … ) ;
  • date with time-of-day in UTC value
    For a database type akin to SQL-standard TIMESTAMP WITH TIME ZONE, use java.time.Instant.
    • Instant instant = myResultSet.getObject( … , Instant.class ) ;
    • myPreparedStatement.setObject( instant , … ) ;
  • date-only 值
    对于类似于 SQL-standard 的数据库类型DATE,请使用java.time.LocalDate.
    • LocalDate ld = myResultSet.getObject( … , LocalDate.class ) ;
    • myPreparedStatement.setObject( ld , … ) ;
  • date with time-of-day in UTC value
    对于类似于 SQL-standard 的数据库类型TIMESTAMP WITH TIME ZONE,使用java.time.Instant.
    • Instant instant = myResultSet.getObject( … , Instant.class ) ;
    • myPreparedStatement.setObject( instant , … ) ;

Details

细节

The question and other answers seem to be over-thinking the issue. A java.sql.Dateis merely a java.util.Datewith its time set to 00:00:00.

问题和其他答案似乎过度思考了这个问题。一个java.sql.Date仅仅是一个java.util.Date其时间设置为00:00:00

From the java.sql.Date doc(italicized text is mine)…

java.sql.Date 文档(斜体文本是我的)...

Class Date

java.lang.Object

????java.util.Date????????← Inherits from j.u.Date

????????java.sql.Date

A thin wrapper around a millisecond value that allows JDBC to identify this as an SQL DATE value. A milliseconds value represents the number of milliseconds that have passed since January 1, 1970 00:00:00.000 GMT.??← Time-of-day set to Zero, midnight GMT/UTC

To conform with the definition of SQL DATE, the millisecond values wrapped by a java.sql.Date instance must be 'normalized' by setting the hours, minutes, seconds, and milliseconds to zero in the particular time zone with which the instance is associated.

上课日期

对象

??????java.util.Date???????? ← 继承自 juDate

????????java.sql.Date

毫秒值的薄包装器,允许 JDBC 将其标识为 SQL DATE 值。毫秒值表示自 1970 年 1 月 1 日 00:00:00.000 GMT 以来经过的毫秒数。?? ← 时间设置为零,午夜 GMT/UTC

为了符合 SQL DATE 的定义,java.sql.Date 实例包装的毫秒值必须通过在实例关联的特定时区中将小时、分钟、秒和毫秒设置为零来“标准化” .

Date-Only versus Date-Time

仅日期与日期时间

The core problem is:

核心问题是:

  • SQL
    In SQL, the DATEdata type stores a date-only, without a time-of-day.
  • JAVA
    In the badly designed date-time library bundled with the early versions of Java, they failed to include a class to represent a date-only.
  • SQL
    在 SQL 中,DATE数据类型只存储日期,不存储时间。
  • JAVA
    在与早期 Java 版本捆绑在一起的设计糟糕的日期时间库中,它们未能包含一个表示仅日期的类。

Instead of creating a date-only class, the Java team made a terrible hack. They took their date-time class (the misnamed java.util.Dateclass, containing both date andtime) and extended it to have an instance set its time-of-day to midnight UTC, 00:00:00. That hack, that subclass of j.u.Date, is java.sql.Date.

Java 团队没有创建一个仅限日期的类,而是做了一个可怕的 hack。他们采用了日期时间类(错误命名的java.util.Date类,包含日期时间)并将其扩展为有一个实例将其时间设置为UTC午夜, 00:00:00。那个hack,juDate的子类,是java.sql.Date.

All this hacking, poor design, and misnaming has made a confusing mess.

所有这些黑客行为、糟糕的设计和错误的命名都造成了混乱。

Which To Use

使用哪个

So when to use which? Simple, after cutting through the confusion.

那么什么时候使用哪个?简单,在消除混乱之后。

  • When reading or writing to a database's date-only column, use java.sql.Dateas it clumsily tries to mask its time-of-day.
  • Everywhere else in Java, where you need a time-of-dayalong with your date, use java.util.Date.
  • When you have a java.sql.Date in hand but need a java.util.Date, simply pass the java.sql.Date. As a subclass, a java.sql.Date isa java.util.Date.
  • 读取或写入数据库的仅日期列时,请使用java.sql.Date它,因为它笨拙地试图掩盖其时间。
  • 在 Java 中的其他任何地方,如果您需要一天中时间和日期,请使用java.util.Date.
  • 当您手头有 java.sql.Date 但需要 java.util.Date 时,只需传递 java.sql.Date。作为子类,java.sql.Datejava.util.Date

Even Better

更好

In modern Java, you now have a choice of decent date-time libraries to supplant the old and notoriously troublesome java.util.Date, Calendar, SimpleTextFormat, and java.sql.Date classes bundled with Java. The main choices are:

在现代 Java 中,您现在可以选择合适的日期时间库来取代与 Java 捆绑在一起的旧的、臭名昭著的麻烦 java.util.Date、Calendar、SimpleTextFormat 和 java.sql.Date 类。主要选择有:

Both offer a LocalDateclass to represent a date only, with no time-of-day and no time zone.

两者都提供一个LocalDate仅表示日期的类,没有时间和时区。

A JDBC driverupdated to JDBC 4.2 or later can be used to directly exchange java.timeobjects with the database. Then we can completely abandon the ugly mess that is the date-time classes in the java.util.* and java.sql.* packages.

一个JDBC驱动程序更新到JDBC 4.2或更高版本可用于直接交换java.time与数据库对象。然后我们可以完全放弃 java.util.* 和 java.sql.* 包中日期时间类的丑陋混乱。

setObject | getObject

设置对象 | 获取对象

This articlepublished by Oracle explains that the JDBC in Java 8 has been updated transparently to map a SQL DATEvalue to the new java.time.LocalDate type if you call getObjectand setObjectmethods.

Oracle 发布的这篇文章解释说,Java 8 中的 JDBC 已被透明更新,DATE如果您调用getObjectsetObject方法,则将SQL值映射到新的 java.time.LocalDate 类型。

In obtuse language, the bottom of the JDBC 4.2 update specconfirms that article, with new mappings added to the getObjectand setObjectmethods.

在钝语言中,JDBC 4.2 更新规范的底部证实了该文章,并在getObjectsetObject方法中添加了新映射。

myPreparedStatement.setObject( … , myLocalDate ) ;

…and…

…和…

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

Convert

转变

The spec also says new methods have been added to the java.sql.Date class to convert back and forth to java.time.LocalDate.

该规范还表示,新方法已添加到 java.sql.Date 类中,以便来回转换为 java.time.LocalDate。

Time Zone

时区

The old java.util.Date, java.sql.Date, and java.sql.Timestampare always in UTC. The first two (at least) have a time zone buried deep in their source code but is used only under-the-surface such as the equalsmethod, and has no getter/setter.

旧的java.util.Datejava.sql.Datejava.sql.Timestamp始终使用UTC。前两个(至少)在其源代码中深埋了一个时区,但仅在表面下使用,例如equals方法,并且没有 getter/setter。

More confusingly, their toStringmethods apply the JVM's current default time zone. So to the na?ve programmer it seemslike they have a time zone but they do not.

更令人困惑的是,他们的toString方法应用了 JVM 当前的默认时区。所以对于天真的程序员来说,他们似乎有一个时区,但他们没有。

Both the buried time zone and the toStringbehavior are two of many reasons to avoid these troublesome old legacy classes.

隐藏时区和toString行为都是避免这些麻烦的旧遗留类的众多原因中的两个。

Write your business logic using java.time(Java 8 and later). Where java.time lacks, use Joda-Time. Both java.time and Joda-Time have convenient methods for going back and forth with the old classes where need be.

使用java.time(Java 8 及更高版本)编写业务逻辑。在 java.time 缺乏的地方,使用Joda-Time。java.time 和 Joda-Time 都有方便的方法来在需要的地方来回使用旧类。

Replacements:

更换:

The Instantclass represents a moment on the timeline in UTCwith a resolution of nanoseconds(up to nine (9) digits of a decimal fraction).

Instant级表示时间轴上的时刻UTC,分辨率为纳秒(最多小数的9个位数)。

All three java.time.Local…classes are all lacking any concept of time zoneor offset-from-UTC.

所有三个java.time.Local…类都缺乏任何时区概念或offset-from-UTC



About java.time

关于java.time

The java.timeframework is built into Java 8 and later. These classes supplant the troublesome old legacydate-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

java.time框架是建立在Java 8和更高版本。这些类取代了麻烦的旧的遗留日期时间类,例如java.util.Date, Calendar, & SimpleDateFormat

The Joda-Timeproject, now in maintenance mode, advises migration to the java.timeclasses.

现在处于维护模式Joda-Time项目建议迁移到java.time类。

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

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

You may exchange java.timeobjects directly with your database. Use a JDBC drivercompliant with JDBC 4.2or later. No need for strings, no need for java.sql.*classes.

您可以直接与您的数据库交换java.time对象。使用符合JDBC 4.2或更高版本的JDBC 驱动程序。不需要字符串,不需要类。java.sql.*

Where to obtain the java.time classes?

从哪里获得 java.time 类?

The ThreeTen-Extraproject extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

ThreeTen-额外项目与其他类扩展java.time。该项目是未来可能添加到 java.time 的试验场。你可能在这里找到一些有用的类,比如IntervalYearWeekYearQuarter,和更多

回答by kostja

In general, I find it advisable to use the java.util.Date, since you can use it anywhere in your program without either converting the type or polluting your application with SQL-specific code.

通常,我认为最好使用java.util.Date,因为您可以在程序中的任何位置使用它,而无需转换类型或使用 SQL 特定代码污染您的应用程序。

I am not aware of a scenario where 'java.sql.Date' would be a better fit.

我不知道“java.sql.Date”更适合的场景。

回答by Petr Mensik

Well, according to this articleyou can use javax.sql.Datewithout @Temporalannotation which can save some coding from you. However java.util.Dateis easier to use across your whole application.

好吧,根据这篇文章,您可以在javax.sql.Date没有@Temporal注释的情况下使用,这可以节省您的一些编码。但是java.util.Date在整个应用程序中更易于使用。

So I would use

所以我会用

@Column(name = "date")
@Temporal(TemporalType.DATE)
private java.util.Date date;

回答by Sandeep Kumar

According to Java doc, it is suggested to use appropriate Date type as per underlying database. However, with Java 8, a rich set of classes under java.time package have been provided and it must be used if application is written with Java 8.

根据 Java 文档,建议根据底层数据库使用适当的 Date 类型。但是,Java 8 在 java.time 包下提供了一组丰富的类,如果应用程序是用 Java 8 编写的,则必须使用它。

The class javaxjava.sql.Date extends java.util.Date with minor changes for miliseconds container so that it can support the Database DATE type effectively. This, we can save the @Temporal annotation typing from entity class.

类 javaxjava.sql.Date 扩展了 java.util.Date 对毫秒容器进行了微小的更改,以便它可以有效地支持数据库 DATE 类型。这样,我们可以保存实体类中的 @Temporal 注释类型。

However, java.util.Date could be used for better scalability in entire application so that it can be easily used to store time along with date.

但是,java.util.Date 可以用于在整个应用程序中获得更好的可伸缩性,以便可以轻松地将时间与日期一起存储。