java.util.Date vs . java.sql.Date:什么时候使用哪个,为什么?
当前回答
祝贺您,您已经解决了JDBC最让我头疼的问题:日期类处理。
基本上,数据库通常至少支持三种形式的datetime字段,即date、time和timestamp。它们中的每一个在JDBC中都有一个对应的类,并且它们都扩展了java.util.Date。这三者的快速语义如下:
java.sql.Date对应于SQL DATE,这意味着它存储年、月和日,而忽略小时、分钟、秒和毫秒。此外sql。日期不受时区限制。 java.sql.Time对应于SQL TIME,很明显,它只包含有关小时、分钟、秒和毫秒的信息。 java.sql.Timestamp与SQL TIMESTAMP相对应,SQL TIMESTAMP是精确到纳秒的日期(请注意util. TIMESTAMP是精确到纳秒的日期)。日期只支持毫秒!),可自定义精度。
在使用与这三种类型相关的JDBC驱动程序时,最常见的错误之一是这些类型被错误地处理。这意味着sql。Date是特定于时区的,sql。时间包含当前的年、月、日等等。
最后:用哪一个呢?
实际上这取决于字段的SQL类型。PreparedStatement有三个值的设置器,#setDate()是sql的设置器。日期,#setTime() sql。sql.Timestamp的时间和#setTimestamp()。
请注意,如果您使用ps.setObject(fieldIndex, utilDateObject);你可以给出一个正常的util。大多数JDBC驱动程序会很高兴地处理它,就好像它是正确的类型一样,但是当您随后请求数据时,您可能会注意到您实际上遗漏了一些东西。
我的意思是,这些日期都不应该使用。
我所说的是将毫秒/纳秒保存为普通的长度,并将它们转换为您正在使用的任何对象(强制性的joda-time插头)。一种简单的方法是将日期组件存储为一个长时间组件,将时间组件存储为另一个长时间组件,例如现在将存储为20100221和154536123。这些神奇的数字可以在SQL查询中使用,并且可以从数据库移植到另一个数据库,并且可以让您完全避免JDBC/Java Date API:s的这一部分。
其他回答
博士tl;
用都没有。
java.time.Instant取代java.util.Date java.time.LocalDate替换java.sql.Date
既不
java.util.Date vs . java.sql.Date:什么时候使用哪个,为什么?
这两个类都很糟糕,在设计和实现上都有缺陷。像避免鼠疫冠状病毒一样。
请使用java。在JSR 310中定义。这些类是用于处理日期-时间处理的行业领先框架。它们完全取代了可怕的遗留类,如Date、Calendar、SimpleDateFormat等。
java.util.Date
第一个,java.util.Date表示UTC中的一个时刻,即与UTC的零小时-分钟-秒的偏移量。
java.time.Instant
现在被java.time.Instant取代。
Instant instant = Instant.now() ; // Capture the current moment as seen in UTC.
java.time.OffsetDateTime
Instant是java.time的基本构建块类。为了获得更大的灵活性,可以将OffsetDateTime设置为ZoneOffset。同样的目的:表示UTC时间。
OffsetDateTime odt = OffsetDateTime.now( ZoneOffset.UTC ) ;
您可以在JDBC 4.2或更高版本中使用PreparedStatement::setObject将该对象发送到数据库。
myPreparedStatement.setObject( … , odt ) ;
检索。
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
java.sql.Date
date类也很糟糕,过时了。
该类只表示日期,没有时间和时区。不幸的是,在一个糟糕的设计中,这个类继承了java.util.Date,它表示一个时刻(一个UTC时间的日期)。因此,这个类只是假装只有日期,而实际上携带了一个时间和UTC的隐式偏移量。这引起了很多困惑。永远不要使用这个类。
java.time.LocalDate
相反,使用java.time.LocalDate只跟踪一个日期(年、月、日),而不跟踪任何时间、任何时区或偏移量。
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
LocalDate ld = LocalDate.now( z ) ; // Capture the current date as seen in the wall-clock time used by the people of a particular region (a time zone).
发送到数据库。
myPreparedStatement.setObject( … , ld ) ;
检索。
LocalDate ld = myResultSet.getObject( … , LocalDate.class ) ;
关于java.time
java。时间框架内置于Java 8及更高版本中。这些类取代了麻烦的旧遗留日期-时间类,如java.util。日期,日历和简单日期格式。
要了解更多,请参阅Oracle教程。搜索Stack Overflow可以找到很多例子和解释。规范是JSR 310。
Joda-Time项目现在处于维护模式,建议迁移到java。时间类。
你可以交换java。Time对象直接使用数据库。使用符合JDBC 4.2或更高版本的JDBC驱动程序。不需要字符串,不需要java。sql。*类。
从哪里获取java。时间类?
Java SE 8、Java SE 9、Java SE 10、Java SE 11及更高版本——带有捆绑实现的标准Java API的一部分。 Java 9增加了一些小特性并进行了修复。 Java SE 6和Java SE 7 大部分的java。时间功能在ThreeTen-Backport中向后移植到Java 6和7。 安卓 后续版本的Android捆绑实现的java。时间类。 对于早期的Android (<26), ThreeTenABP项目适应ThreeTen-Backport(如上所述)。参见如何使用ThreeTenABP....
使用java.sql.Date的唯一时间是在PreparedStatement.setDate中。否则,使用java.util.Date。它告诉ResultSet。getDate返回一个java.sql.Date,但它可以直接分配给java.util.Date。
date表示精确到毫秒的特定时刻。它表示不带时区的日期和时间信息。date类实现了可序列化、可克隆和可比较的接口。它被java.sql继承。Date、java.sql.Time和java.sql.Timestamp接口。
java.sql.Date扩展了java.util.Date类,它表示没有时间信息的日期,只应该在处理数据库时使用。为了符合SQL DATE的定义,java.sql.Date实例包装的毫秒值必须“规范化”,方法是在实例关联的特定时区中将小时、分钟、秒和毫秒设置为零。
它继承了java.util.Date的所有公共方法,如getHours()、getMinutes()、getSeconds()、setHours()、setMinutes()、setSeconds()。由于java.sql.Date不存储时间信息,它覆盖了java.util. date中的所有时间操作,并且所有这些方法在调用时会抛出java.lang.IllegalArgumentException,这从它们的实现细节中可以明显看到。
祝贺您,您已经解决了JDBC最让我头疼的问题:日期类处理。
基本上,数据库通常至少支持三种形式的datetime字段,即date、time和timestamp。它们中的每一个在JDBC中都有一个对应的类,并且它们都扩展了java.util.Date。这三者的快速语义如下:
java.sql.Date对应于SQL DATE,这意味着它存储年、月和日,而忽略小时、分钟、秒和毫秒。此外sql。日期不受时区限制。 java.sql.Time对应于SQL TIME,很明显,它只包含有关小时、分钟、秒和毫秒的信息。 java.sql.Timestamp与SQL TIMESTAMP相对应,SQL TIMESTAMP是精确到纳秒的日期(请注意util. TIMESTAMP是精确到纳秒的日期)。日期只支持毫秒!),可自定义精度。
在使用与这三种类型相关的JDBC驱动程序时,最常见的错误之一是这些类型被错误地处理。这意味着sql。Date是特定于时区的,sql。时间包含当前的年、月、日等等。
最后:用哪一个呢?
实际上这取决于字段的SQL类型。PreparedStatement有三个值的设置器,#setDate()是sql的设置器。日期,#setTime() sql。sql.Timestamp的时间和#setTimestamp()。
请注意,如果您使用ps.setObject(fieldIndex, utilDateObject);你可以给出一个正常的util。大多数JDBC驱动程序会很高兴地处理它,就好像它是正确的类型一样,但是当您随后请求数据时,您可能会注意到您实际上遗漏了一些东西。
我的意思是,这些日期都不应该使用。
我所说的是将毫秒/纳秒保存为普通的长度,并将它们转换为您正在使用的任何对象(强制性的joda-time插头)。一种简单的方法是将日期组件存储为一个长时间组件,将时间组件存储为另一个长时间组件,例如现在将存储为20100221和154536123。这些神奇的数字可以在SQL查询中使用,并且可以从数据库移植到另一个数据库,并且可以让您完全避免JDBC/Java Date API:s的这一部分。
LATE EDIT:从Java 8开始,你不应该使用Java .util. date或Java .sql. date,如果你可以避免它,而宁愿使用Java .util. date。时间包(基于Joda)而不是其他任何东西。如果你没有使用Java 8,以下是最初的回复:
java.sql.Date -当你调用使用它的库(如JDBC)的方法/构造函数时。没有否则。对于不显式处理JDBC的应用程序/模块,您不希望向数据库库引入依赖项。
date -当使用使用它的库时。否则,尽可能少,原因如下:
It's mutable, which means you have to make a defensive copy of it every time you pass it to or return it from a method. It doesn't handle dates very well, which backwards people like yours truly, think date handling classes should. Now, because j.u.D doesn't do it's job very well, the ghastly Calendar classes were introduced. They are also mutable, and awful to work with, and should be avoided if you don't have any choice. There are better alternatives, like the Joda Time API (which might even make it into Java 7 and become the new official date handling API - a quick search says it won't).
如果您觉得引入像Joda这样的新依赖项有点过分,那么对于对象中的时间戳字段使用long也不是那么糟糕,尽管我自己在传递它们时通常将它们包装在j.u.D中,以确保类型安全和作为文档。
推荐文章
- 禁用IntelliJ星(包)导入?
- 面试问题:检查一个字符串是否是另一个字符串的旋转
- NVL和Coalesce之间的Oracle差异
- 将文件加载为InputStream的不同方法
- 到底是什么导致了堆栈溢出错误?
- 为什么Android工作室说“等待调试器”如果我不调试?
- 在SQL server查询中将NULL替换为0
- 在SQL中修改表的模式名
- Java:路径vs文件
- ExecutorService,如何等待所有任务完成
- 为什么在JavaScript的Date构造函数中month参数的范围从0到11 ?
- 如何在SQL Server 2005的一条语句中更新两个表?
- Maven依赖Servlet 3.0 API?
- 在Windows批处理脚本中格式化日期和时间
- 如何在IntelliJ IDEA中添加目录到应用程序运行概要文件中的类路径?