这是一个简单的问题:我知道并且几乎每个人都听说在Jdbc调用中使用java.util.Date
进行任何操作都是个坏主意。您应该使用java.sql.Date
或java.sql.Time
或java.sql.Timestamp
。但是,有什么理由不去?我无法找到一篇好的博客文章或SO帖子解释它,除非有时人们看到"奇怪的行为"。
谢谢!
修改:
所以,我看过this post。是的,该帖子的唯一部分是我的问题的答案
...对于大多数JDBC驱动程序来说,它们会愉快地吞噬它,就像它一样 正确的类型,但是当您之后请求数据时,您可以 请注意,你实际上缺少了东西。
但是,这并没有真正回答为什么。
答案 0 :(得分:16)
好的,所以在阅读了所有答案中的所有信息,以及评论中指出的其他帖子等等之后,我决定总结一下我学到的东西:
从我所看到的,有三层
JDBC wrapper calls (e.g. Spring's SimpleJdbcTemplate)
|
|
Raw JDBC calls (e.g. PreparedStatement)
|
|
JDBC driver (e.g. Oracle)
许多JDBC类包装器(例如Spring着名的SimpleJdbcTemplate
)允许您在执行SQL语句时将Map<String, Object>
作为参数映射。这非常简单,因为当它在引擎盖下使用原始JDBC时,它会将对象的所有转换交给正确的java.sql.*
类型。第一个问题在于:如果您有以下内容会发生什么:
Map<String, Object> paramMap = new HashMap<String,Object>();
paramMap.put("p_some_data", new java.util.Date());
Spring将它转换为什么?一个java.sql.Date
?一个java.sql.Timestamp
?一个java.sql.Time
?或者甚至把它投到java.lang.Object
?正如this answer to a different question和another fellow here中@BalusC所解释的那样,这三种java.sql
类型之间存在很大差异。所以,第一个原因不使用java.util.Date
:您不能依赖框架的内部约定来为您处理转换。
现在,讨论原始JDBC调用,@ The Nail explained,你需要这些java.sql
类型来进行JDBC调用,以及he's absolutely right,这是给我的消息。但是,仍有可怕的setObject
电话。从阅读the JavaDoc for that call开始,如果给出一个java.util.Date
,它会做些什么似乎有些含糊不清。因此,第二个原因不使用它是因为那里含糊不清。
最后,谈谈司机的水平。我可以证明个人经验,有时Spring与Oracle驱动程序一起使用java.util.Date
。有时。然后有时它没有。所以,因为我不知道任何特定驱动程序的任何特定版本将如何处理java.util.Date
,所以最好是明确的。这是第三个原因。
一般来说,原因似乎是:“JDBC不应该与java.util.Date
一起使用。如果你这样做,你就不能确定会发生什么。”这对我来说是一个很好的理由:)
答案 1 :(得分:8)
java.util.Date的瘦包装器,允许JDBC API将其标识为SQL TIMESTAMP值。它增加了保持SQL TIMESTAMP小数秒值的功能,允许将小数秒的指定精度设置为纳秒。 Timestamp还提供格式化和解析操作,以支持时间戳值的JDBC转义语法。
它是时间戳的精确度(由DB提供),它可以与java.util.Date
保持一致。
假设,如果我们使用java.util.Date
对象来表示DB中的时间戳值,那么该对象表示的值将不会表示相同的值(如在DB中),因为它不能保持“小数”秒到精度为纳秒“。
答案 2 :(得分:2)
至于Date
,这很简单:PreparedStatement.setDate
需要java.sql.Date
,而不是java.util.Date
。
您可以像这样转换java.util.Date
到java.sql.Date
:
java.sql.Date sqlDate = new java.sql.Date(date.getTime());
答案 3 :(得分:2)
java.util.Date
表示一般的DateTime Value.Basically是Java Type。
java.sql.Date
特定用于将Java Object对象模型映射到SQL数据类型,该数据类型用于SQL数据。 (Sql Type不是Java Type)。