java.util.Date与java.sql.Date的比较:何时使用哪个?为什么?
恭喜你,你已经用jdbc:日期类处理击中了我最喜欢的宠物。
基本上,数据库通常支持至少三种形式的日期时间字段,分别是日期、时间和时间戳。每个类在JDBC中都有一个对应的类,并且每个类都扩展了java.util.Date。这三种语言的快速语义如下:
- java.sql.Date对应于SQL日期,即存储年、月和日,而忽略小时、分钟、秒和毫秒。另外,sql.Date与时区无关。
- java.sql.Time对应于SQL时间,很明显,它只包含有关小时、分钟、秒和毫秒的信息。
- java.sql.Timestamp对应于精确到纳秒的SQL时间戳(注意,util.Date只支持毫秒!)可定制的精准度。
对于这三种类型使用JDBC驱动程序时,最常见的错误之一是类型处理不正确。这意味着sql.Date是特定于时区的,sql.Time包含当前年份、月份和日期等。
最后:用哪一个?
实际上,这取决于字段的SQL类型。PreparedStatement对所有三个值都有设定值,#setDate()是sql.Date的设定值,#setTime()是sql.Time的设定值,#setTimestamp()是sql.Timestamp的设定值。
请注意,如果您使用ps.setObject(fieldIndex, utilDateObject);,实际上可以为大多数JDBC驱动程序提供一个正常的util.Date,这些驱动程序将愉快地吞食它,就像它是正确的类型一样,但是当您随后请求数据时,您可能会注意到您实际上丢失了一些东西。
我真的是说所有的日期都不应该使用。
我要说的是,将毫秒/纳秒保存为普通的长时间,并将它们转换为您正在使用的任何对象(强制性的Joda时间插头)。一种可以做的黑客方法是将日期组件作为一个长时间组件存储,例如现在将是20100221和154536123。这些神奇的数字可以在SQL查询中使用,并且可以从数据库移植到另一个,并允许您完全避免JDBC/JavaDeAP:s的这一部分。
- 回答得很好。但对于DBA来说,存储日期是否有点不友好?
- 然而,DBA:S通常倾向于他们的RDBMS选择,而拒绝直接涉及RDBMS的所有东西(我在看你,Oracle FANS),而Java应用程序希望与它们一起工作。就个人而言,我根本不想把我的逻辑放到数据库中。
- 我的MySQL列是DATETIME,但执行PS.SETDATE(new java. sql .Dead(myObjut.GeCaldDATE())(GETTIMEY()));我正在丢失毫秒部分,如何修复这个问题?
- 不要丢失你的毫秒:新的java. sql .TimePress(UTILAD.GETTIME())
- 您在一个地方提到了sql.date-存储时区信息,而在另一个地方却不存储时区信息。所以要得出正确的结论:sql.date不应该保存时区信息,但它是这样的?!
- 我提到这是一个常见的bug,它是TZ特有的,而规范不应该如此。
- 如果我不知道我要存储的日期的实际时间怎么办?例如,出生日期,或者事件发生的日期(没有比这一天更大的粒度)?如果我存储一个特定的时间戳,那么这个时间戳在某些时区中可能有一些与它相关联的日期,而不是它要表示的日期。(世界上任何时候都至少有两个日期在某个地方发生,在10:00到11:59 UTC之间有三个独立的日期。)
- 将日期转换为使用to_char的字符串,并转换为所需的格式。如果您想从数据库中检索日期。
后期编辑:从Java 8开始,既不使用EDCOX1,也不使用EDCOX1,也不使用EDCOX1 0。如果您完全可以避免使用它,而是更喜欢使用EDCOX1×25封装(基于JoDA)而不是其他任何东西。如果你不在Java 8上,这里是最初的回应:
java.sql.Date—当您调用使用它的库(如jdbc)的方法/构造函数时。否则不行。对于不显式处理JDBC的应用程序/模块,您不希望向数据库库引入依赖项。
java.util.Date—当使用它的库时。否则,由于以下几个原因,尽可能少地:
它是可变的,这意味着每次你将它传递给一个方法或者从一个方法返回它时,你都必须对它做一个防御性的拷贝。
它不能很好地处理日期,这倒是像你这样的人,认为日期处理类应该。
现在,由于J.U.D做得不太好,引入了可怕的Calendar类。它们也是可变的,很难使用,如果你没有选择的话应该避免。
还有更好的选择,比如JoDA时间API(,它甚至可以进入Java 7,并成为新的官方数据处理API ——一个快速搜索称它不会)。
如果您觉得引入一个新的依赖项(如joda)有点过分,那么在对象中使用时间戳字段并不是很糟糕,尽管我在传递它们时通常用J.U.D包装它们,以确保类型安全和作为文档。
- 在数据库中存储时,为什么我们更喜欢java.time而不是java.sql?我对这句话很感兴趣,但我想知道为什么:)
使用java.sql.Date的唯一时间是在PreparedStatement.setDate中。否则,使用java.util.Date。说明ResultSet.getDate返回java.sql.Date,但可以直接分配给java.util.Date。
- ehm,resultset getdate()返回sql.date(扩展了util.date)。
- @Esko-"ehm",我在你评论(和投反对票)之前修正了这一点。
- 需要注意的是,可以将java.sql.date分配给java.util.date的原因是,第一个是第二个的子类。
- 为什么它"告诉"当一个EDOCX1[0]扩展到另一个EDOCX1[1]时,该EDOCX1[0]可以被分配给它?你想说什么?
我有同样的问题,我发现将当前日期插入准备好的语句中最简单的方法是:
1
| preparedStatement. setDate(1, new java. sql. Date(new java. util. Date(). getTime())); |
。
Java中的JavaUTILDATE类代表一个特定的时刻(例如,2013,11月25日16:30:45到毫秒),但是DB中的日期数据类型仅表示日期(例如,2013 11月25日)。为了防止错误地将JavaUTILDATE对象提供给数据库,Java不允许您直接将SQL参数设置为JavaUTILDATE:
但它仍然允许您通过强制/意图来实现这一点(那么,DB驱动程序将忽略小时和分钟)。这是通过java.sql.date类完成的:
号
Java.Q.L.Dead对象可以及时存储一个时刻(以便于从Java.U.D.Dead构造),但是如果您试图请求它的小时数(强制执行它仅作为日期的概念),就会抛出异常。DB驱动程序应该能够识别这个类,并且只需要在几个小时内使用0。试试这个:
1 2 3 4 5 6
| 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());
} |