java.util.Date vs . java.sql.Date:什么时候使用哪个,为什么?


当前回答

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中,以确保类型安全和作为文档。

其他回答

使用java.sql.Date的唯一时间是在PreparedStatement.setDate中。否则,使用java.util.Date。它告诉ResultSet。getDate返回一个java.sql.Date,但它可以直接分配给java.util.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的这一部分。

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中,以确保类型安全和作为文档。

date类在Java中表示一个特定的时刻(例如,.g。, 2013 Nov 25 16:30:45精确到毫秒),但是DB中的DATE数据类型只表示一个日期(例如,2013 Nov 25)。为了防止您错误地向DB提供Java .util. date对象,Java不允许您直接将SQL参数设置为Java .util. date:

PreparedStatement st = ...
java.util.Date d = ...
st.setDate(1, d); //will not work

但是它仍然允许您通过强制/意图来这样做(然后DB驱动程序将忽略小时和分钟)。这是通过java.sql.Date类完成的:

PreparedStatement st = ...
java.util.Date d = ...
st.setDate(1, new java.sql.Date(d.getTime())); //will work

java.sql.Date对象可以存储时刻(因此很容易从java.util.Date构造它),但如果您试图询问它的小时数(以强制其仅为日期的概念),则会抛出异常。DB驱动程序应该能够识别这个类,并且只使用0表示小时数。试试这个:

public static void main(String[] args) {
  java.util.Date d1 = new java.util.Date(12345);//ms since 1970 Jan 1 midnight
  java.sql.Date d2 = new java.sql.Date(12345);
  System.out.println(d1.getHours());
  System.out.println(d2.getHours());
}

我有同样的问题,我发现插入当前日期到一个准备好的语句的最简单的方法是:

preparedStatement.setDate(1, new java.sql.Date(new java.util.Date().getTime()));