错过了在 Java 8 中修复 JDBC 日期处理的机会?
任何 Java 8 + JDBC 专家都可以告诉我以下推理中是否有问题?而且,如果在神的秘密中,为什么没有这样做?
A 是 JDBC 当前用于映射到 DATE SQL 类型的类型,该类型表示不带时间和时区的日期。但是这个类的设计很糟糕,因为它实际上是 的子类,它存储了精确的瞬间,直到毫秒。java.sql.Date
java.util.Date
因此,为了在数据库中表示日期 2015-09-13,我们被迫选择一个时区,在该时区中解析字符串“2015-09-13T00:00:00.000”作为 java.util.Date 以获取毫秒值,然后从该毫秒值构造 a,最后调用预准备语句,传递一个包含所选时区的日历,以便 JDBC 驱动程序能够从该毫秒值正确重新计算日期 2015-09-13。通过在任何地方使用默认时区,并且不传递日历,此过程变得更加简单。java.sql.Date
setDate()
Java 8 引入了一个 LocalDate 类,该类更适合 DATE 数据库类型,因为它不是一个精确的时刻,因此不依赖于时区。Java 8还引入了默认方法,这些方法允许对ReadkEdStatement和ResultSet接口进行向后兼容的更改。
那么,我们难道没有错过一个巨大的机会来清理JDBC中的混乱,同时仍然保持向后兼容性吗?Java 8 可以简单地将这些默认方法添加到 PreparedStatement 和 ResultSet 中:
default public void setLocalDate(int parameterIndex, LocalDate localDate) {
if (localDate == null) {
setDate(parameterIndex, null);
}
else {
ZoneId utc = ZoneId.of("UTC");
java.util.Date utilDate = java.util.Date.from(localDate.atStartOfDay(utc).toInstant());
Date sqlDate = new Date(utilDate.getTime());
setDate(parameterIndex, sqlDate, Calendar.getInstance(TimeZone.getTimeZone(utc)));
}
}
default LocalDate getLocalDate(int parameterIndex) {
ZoneId utc = ZoneId.of("UTC");
Date sqlDate = getDate(parameterIndex, Calendar.getInstance(TimeZone.getTimeZone(utc)));
if (sqlDate == null) {
return null;
}
java.util.Date utilDate = new java.util.Date(sqlDate.getTime());
return utilDate.toInstant().atZone(utc).toLocalDate();
}
当然,同样的理由也适用于对 TIMESTAMP 类型的即时支持,以及对 TIME 类型的 LocalTime 的支持。