Oracle 不会更改 JDBC 规范。我们更新了 Oracle 数据库 JDBC 驱动程序文档。如果文档中有任何令人困惑或不正确的内容,我们将对其进行修复。不过,JDBC 规范没有变化。
以前版本的驱动程序不一致。在某些地方,他们将秒数归零。在其他地方,他们没有。在 12.1 中,我们使驱动程序保持一致。问题是,什么是正确的行为。无论哪种方式,一些客户都会看到行为发生变化。
经过漫长而激烈的辩论,我们决定对 Oracle 数据库客户来说最好的事情不是将秒数归零。让我解释。
- ANSI SQL DATE 类型不存储秒。JDBC 规范主要假定 ANSI SQL。
- Oracle 数据库 DATE 类型确实存储秒。ANSI SQL 委员会的成员向我保证,这完全符合 ANSI SQL。
- JDBC 的目标是公开数据库。JDBC 规范没有定义一些抽象数据库,目的是驱动程序实现该抽象数据库。JDBC 驱动程序需要公开数据库的详细信息,而不是隐藏它们。JDBC 定义了一些工具来抽象一些数据库细节,但程序员可以选择使用或不使用这些工具。
java.sql.Date
不会强制执行零秒行为,尽管它很容易做到。程序有责任强制执行或不强制执行该行为。
所以,Oracle DATE 有秒数。Oracle JDBC 驱动程序公开了 Oracle 数据库。如果getDate
将秒数归零,那将丢失数据。对于某些用户来说,这无关紧要,但对于其他用户来说却是。由于 Oracle DATE 存储秒,因此许多 Oracle 数据库在 DATE 列中存储具有秒精度的时间。在这些情况下将秒归零会丢失信息。
如果程序将具有非零秒数的日期传递给setDate
,则程序创建了一个不合规的日期。如果驱动程序将秒数归零,则驱动程序丢弃了程序提供且数据库可以存储的信息。司机再次丢失了信息。
编写 SQL 或 Java 将 get 和 set 的秒数归零很容易。尽管肯定有可能,但要解决丢失信息的问题更加困难。
所以我们选择让驱动程序始终保持秒数java.sql.Date
。ResultSet.getDate
可以构造一个java.sql.Date
非零秒,但这准确地反映了数据库中的内容。如前所述, Date 的实现可以强制执行此操作,但没有。一种看待它的方法是程序在将日期存储在数据库中时创建了日期,因此这是程序的责任。驱动程序只是使用程序提供的数据。
我真的很抱歉驱动程序之前不一致。我们一直在努力清理不一致和奇怪的角落案例。但我们拥有庞大的安装基础。每次我们更改某些内容,甚至是明显的错误修复时,某处的某些客户都会受到影响。因此,我们尝试在改进驱动程序和保持向后兼容性之间取得平衡。12c 是一个主要版本。我们借此机会做出了一些更明显的改变。我们对这次中断感到遗憾,但认为这对整体客户来说是正确的。