如果 Timestamp 映射到/来自数据库,则 Timestamp#equals() 失败
Posted
技术标签:
【中文标题】如果 Timestamp 映射到/来自数据库,则 Timestamp#equals() 失败【英文标题】:Timestamp#equals() fails if Timestamp is mapped to/from Database 【发布时间】: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
【参考方案1】:
SQL Server DATETIME
的精度为 +/- 3 毫秒:
四舍五入到 0.000、0.003 或 0.007 秒的增量
换句话说,如果您插入一个小于第二小数.001
的值,它将被存储为.000
、.002
为.003
等,从而使等值检查失败。如果您在 Timestamp
中具有亚毫秒精度(例如,存储具有亚秒值 .0001
的 Timestamp
将四舍五入为 .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 fortime
:"Accuracy 100 纳秒(Informatica 中为 1 毫秒)",但是 java.sql.Time
仅具有秒精度,但您应该能够将Timestamp
设置/获取到time
字段,但您会丢失日期信息。以上是关于如果 Timestamp 映射到/来自数据库,则 Timestamp#equals() 失败的主要内容,如果未能解决你的问题,请参考以下文章
我可以将 TIMESTAMP WITH TIME ZONE 或 TIMESTAMP WITH LOCAL TIME ZONE 映射到哪些 Java 数据类型?
如何将 TIMESTAMP 列映射到 ZonedDateTime JPA 实体属性?
如果超过 78 个字符,则使用 TIMESTAMP 的 TO_CHAR 会引发 ORA-01877
csharp 将TimeStamp附加到文件名中 - 来自http://stackoverflow.com/questions/7898392/append-timestamp-to-a-file-n