【问题标题】:Timestamp#equals() fails if Timestamp is mapped to/from Database如果 Timestamp 映射到/来自数据库,则 Timestamp#equals() 失败
【发布时间】:2017-06-06 01:53:11
【问题描述】:

我在我的 MS SQL 数据库中使用DATETIME 来存储日期和时间。

Java 到数据库:preparedStatement.setTimestamp(2, insertObj.getTimestamp());

数据库到 Java:selectedObj.setTimestamp(result.getTimestamp("datetime"));

在我的单元测试中将它们与insertObj.timestamp.equals(selectedObj.timestamp); 进行比较随机返回真或假。

这是一个已知问题吗?我该如何解决?

【问题讨论】:

  • 所以您的数据库列属于这种类型:DATETIME,而您的 Java 变量属于这种类型:java.sql.Timestamp?还有什么 JDBC 驱动程序?
  • @Basil Bourque 是的,这就是您将 DATETIME 值插入数据库的方式,JDBC 中没有“setDatetime()”或其他任何内容,JDBC 驱动程序将正确处理从时间戳到 DATETIME 的转换,它工作了一段时间,有时返回的时间戳与插入的时间戳相差 1ms
  • (A) 你实际上并没有回答我的问题。 (B) 我熟悉 JDBC 的工作原理。 (C) 将示例数据值添加到您的问题中。
  • 您的所有答案都可以在我的问题中找到:Microsoft SQL Server, DATETIME column, java.sql.Timestamp, Microsoft JDBC 4.2

标签: java sql-server datetime jdbc timestamp


【解决方案1】:

SQL Server DATETIME 的精度为 +/- 3 毫秒:

四舍五入到 0.000、0.003 或 0.007 秒的增量

换句话说,如果您插入一个小于第二小数.001 的值,它将被存储为.000.002.003 等,从而使等值检查失败。如果您在 Timestamp 中具有亚毫秒精度(例如,存储具有亚秒值 .0001Timestamp 将四舍五入为 .000),您也可以具有此效果,另见下文。

如果您想要更精确的存储,则需要使用精度为 100 纳秒的DATETIME2,否则您需要考虑舍入,例如检查两个值之间的绝对差是否小于 3毫秒,例如:

Math.abs(insertTimestamp.getTime() - selectedTimestamp.getTime()) < 3

请注意,java.sql.Timestamp 可以包含高达纳秒的精度(因此,如果您在DATETIME2 中存储分辨率高于 100ns 的值,您仍然会遇到此问题)。您通常具有毫秒精度,但如果使用setNanos(用于设置亚秒纳秒值)或从java.time 类之一创建,则可以获得纳秒精度。另请参阅Timestamp API 文档:

注意:此类型是java.util.Date 和单独的纳秒值的组合。 java.util.Date 组件中仅存储整数秒。小数秒 - 纳米 - 是分开的

【讨论】:

  • 精彩的解释,谢谢!还有一个问题:SQL 中的 TIME 数据类型有类似的行为吗?我真的不需要这么精确,我只需要取回我存储的完全相同的值。
  • @Pali,参见documentation for time"Accuracy 100 纳秒(Informatica 中为 1 毫秒)",但是 java.sql.Time 仅具有秒精度,但您应该能够将Timestamp 设置/获取到time 字段,但您会丢失日期信息。
猜你喜欢
  • 1970-01-01
  • 2017-11-24
  • 2019-04-02
  • 2012-07-16
  • 2011-05-03
  • 2016-02-25
  • 2021-03-18
  • 1970-01-01
  • 2019-11-01
相关资源
最近更新 更多