java.util.Date与java.sql.Date的区别
java.util.Date与java.sql.Date的区别
java.util.Date
与java.sql.Date
:什么时候应该使用哪一种,以及为什么?
LATE EDIT: 从Java 8开始,如果你尽可能地避免使用它,你既不应该使用java.util.Date,也不应该使用java.sql.Date,而应该优先使用java.time包(基于Joda)而不是其他任何包。如果你没有使用Java 8,这里是原始的回答:
java.sql.Date
- 当调用使用它的库的方法/构造函数时(如JDBC)。其他情况则不需要。你不想为那些不显式处理JDBC的应用程序/模块引入依赖于数据库库的问题。
java.util.Date
- 当使用使用它的库时。否则,应该尽可能少使用,有几个原因:
-
它是可变的,这意味着你需要每次将它传递到方法中或从方法中返回它时都要进行防御性拷贝。
-
它并不很好地处理日期,这与像我这样保守的人认为日期处理类应该的处理方式不同。
-
现在,由于j.u.D不做好它的工作,可怕的
Calendar
类被引入了。它们也是可变的,很难使用,如果你没有任何选择,应该避免使用。 -
还有更好的选择,比如Joda Time API,(
可能甚至会进入Java 7并成为新的官方日期处理API- 快速搜索显示它不会)。
如果你认为引入类似Joda这样的新依赖关系是过度的,对于对象中的时间戳字段,使用long
也不是很糟糕,虽然我自己在传递它们时通常会将它们包装在j.u.D中,以获得类型安全性和文档。
恭喜,您碰到了我最讨厌的JDBC问题之一:日期类处理。
基本上,数据库通常支持至少三种日期时间字段,分别为日期、时间和时间戳。每种类型在JDBC中都有一个对应的类,并且它们每个都扩展了java.util.Date
。这三种日期时间类型的快速语义如下:
java.sql.Date
对应于SQL DATE,这意味着它存储年、月和日,而小时、分钟、秒和毫秒则被忽略。另外,sql.Date
与时区无关。java.sql.Time
对应于SQL TIME,正如显而易见的,它只包含有关小时、分钟、秒和毫秒的信息。java.sql.Timestamp
对应于SQL TIMESTAMP,是精确到纳秒的日期(请注意,util.Date
仅支持毫秒!)并具有可自定义的精度。
使用JDBC驱动程序时与这三种类型相关的最常见错误之一是类型处理不正确。这意味着sql.Date
具有时区特定性,sql.Time
包含当前年、月和日等等等等。
最后:应该使用哪个?
实际上取决于字段的SQL类型。 PreparedStatement
拥有所有三个值的setter,#setDate()
用于sql.Date
,#setTime()
用于sql.Time
,#setTimestamp()
用于sql.Timestamp
。
请注意,如果您使用ps.setObject(fieldIndex, utilDateObject);
,则可以将普通的util.Date
传递给大多数JDBC驱动程序,它们将高兴地将其视为正确类型。但是,当您之后请求数据时,可能会注意到您实际上缺少一些内容。
我真的想说根本不应该使用任何日期。
我想说的是将毫秒/纳秒另存为普通长整型,并将其转换为您使用的任何对象(强制使用joda-time插件)。可以采用一种诡计的方式,将日期组件存储为一个长整型,将时间组件存储为另一个长整型,例如现在的日期是20100221和154536123。这些魔法数字可以用于SQL查询,并且可从一个数据库移植到另一个数据库,以使您完全避免使用JDBC/Java日期API中的这一部分。