1

我在 Oracle SQL 中遇到了这个奇怪的时间戳到日期转换问题。

下面是 SQL 语句:

String INSERT_SQL = String.format("INSERT INTO AUDIT_TASK (%s, %s, %s, %s) VALUES (AUDIT_TASK_SEQ.nextval,?,?,?)",ID,CLASS_NAME,TASK_STEP_TIMESTAMP,OPERATOR);

java.util.Calendar utcCalendarInstance = Calendar.getInstance(TimeZone .getTimeZone("UTC"));
java.util.Calendar cal = Calendar.getInstance();
final PreparedStatement stmt = con.prepareStatement(INSERT_SQL);
stmt.setString(1, audit.getClassName().getValue());
// Save the timestamp in UTC
stmt.setTimestamp(2,new Timestamp(cal.getTimeInMillis()), utcCalendarInstance);

当我执行此语句时,虽然大多数时候 creation_date 和 task_step_timestamp 日期是相同的,但有时我会生成带有一些虚假日期的 task_step_timestamp - 例如“25-APR-0000”或“00-Jan-0001”等。

  • 身份证 | 创建日期 | Task_step_timestamp
  • 1 |2018 年 4 月 27 日 17:58:53| 25-APR-0000 09:00:45
  • 2 |2018 年 4 月 27 日 18:06:25| 00-1-0001 09:18:25

Oracle DB 中 task_step_timestamp 列的数据类型为“DATE”。

有人可以提出时间戳到日期的这种不一致转换的原因吗?

4

1 回答 1

0

我不明白你为什么在String#format这里使用。只需使用提及显式列的常规插入:

String INSERT_SQL = "INSERT INTO AUDIT_TASK (ID, ERROR_MESSAGE, TASK_STEP_TIMESTAMP, OPERATOR) ";
INSERT_SQL += "VALUES (AUDIT_TASK_SEQ.nextval, ?, ?, ?)";
PreparedStatement stmt = con.prepareStatement(INSERT_SQL);

然后绑定您的值:

stmt.setString(1, audit.getErrorMessage() != null ? audit.getErrorMessage().getValue() : null);
stmt.setTimestamp(2, new Timestamp(cal.getTimeInMillis()), utcCalendarInstance);
stmt.setString(3, audit.getClassName().getValue());

请注意,占位符从左到右依次是错误消息、任务步骤时间戳和运算符。您的原始代码似乎无序地绑定参数。通过使用明确提及列的插入语句,您可以避免此问题。

编辑:

对我来说,为什么您担心时间戳的时区对我来说也没有意义。只需获取自纪元以来的毫秒数,然后让数据库将其存储为 UTC:

Timestamp timestamp = new Timestamp(System.currentTimeMillis());
stmt.setTimestamp(2, timestamp);
于 2018-05-19T10:37:58.577 回答