java.util.Date vs java.sql.Date
java.util.Date
vs java.sql.Date
:何时使用哪些和为什么?
恭喜,你已经用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.Date
时区的, sql.Time
包含当前年份,月份和日期等等。
最后:使用哪一个?
实际上取决于字段的SQL类型。 PreparedStatement
具有所有三个值的setter,其中#setDate()
为sql.Date
, #setTime()
为sql.Time
, #setTimestamp()
为sql.Timestamp
。
请注意,如果你使用ps.setObject(fieldIndex, utilDateObject);
你实际上可以给大多数JDBC驱动程序提供一个正常的util.Date
,它将会愉快地吞噬它,就好像它是正确的类型,但是当你事后请求数据时,你可能会注意到你实际上错过了东西。
我的确在说,根本不应该使用任何日期。
我的意思是将毫秒/纳秒保存为简单的长整型并将它们转换为您正在使用的任何对象(强制性的joda-time插件)。 可以做的一件怪事就是将日期组件作为一个长时间组件存储为另一个组件,例如现在将是20100221和154536123.这些神奇数字可以用于SQL查询,并且可以从数据库移植到另一个,以及将让你完全避免这部分JDBC / Java Date API:s。
LATE EDIT:从Java 8开始,如果你完全可以避免使用java.util.Date
和java.sql.Date
则应该使用java.time
包(基于Joda)而不是其他任何东西。 如果你不在Java 8上,下面是原始响应:
java.sql.Date
- 当您调用使用它的库的方法/构造函数(如JDBC)时。 否则。 您不希望为不明确处理JDBC的应用程序/模块引入依赖关系到数据库库。
java.util.Date
- 使用库时使用它。 否则,出于以下几个原因,尽可能少:
它是可变的,这意味着每次将它传递给方法或从方法返回时,都必须制作其防御副本。
它不能很好地处理日期,像你这样的倒退者认为日期处理类应该如此。
现在,因为juD没有做得很好,所以引入了可怕的Calendar
类。 它们也是可变的,并且很难处理,如果你没有任何选择,应该避免。
还有更好的选择,比如Joda Time API(甚至可以将它加入Java 7并成为新的官方日期处理API--快速搜索表明它不会)。
如果你觉得引入像Joda这样的新依赖是过时的,那么long
s对于时间戳字段在对象中的使用并不是那么糟糕,尽管我自己通常在将它们传递给它们时将它们包装在juD中,以用于类型安全和作为文档。
使用java.sql.Date
的唯一时间是在PreparedStatement.setDate
。 否则,请使用java.util.Date
。 它告诉ResultSet.getDate
返回一个java.sql.Date
但它可以直接分配给java.util.Date
。