从ResultSet中获取日期以便与java.time类一起使用

36

有没有办法从ResultSet中获取一个与Java 8中的新类java.time兼容的时间类?

我知道你可以使用ResultSetgetDategetTimestamp 方法,但是这些方法返回的是已经过时的java.sql.Date / java.sql.Timestamp对象,因此似乎不好的做法是使用它们来创建ZonedDateTime或类似对象。


3
java.sql.Date等不被官方弃用(没有设置弃用的javadoc标签或注释)。关于你的问题,查找JDBC 4.2 - 是否支持你的数据库(实际上在大多数情况下不可用?),然后使用现有的setObject()getObject()方法。 - Meno Hochschild
3个回答

31
大多数数据库供应商尚不支持JDBC 4.2。该规范说明新的java.time类型(如LocalDate)将/应使用现有的方法setObject(...)getObject()进行支持。无需提供显式转换(无API更改)。
缺少支持的解决方法可以手动转换,如Derby邮件列表中所述。
类似于:
LocalDate birthDate = resultSet.getDate("birth_date").toLocalDate();

正如您所看到的,这些转换使用非废弃类型java.sql.Date等,请参见javadoc

在转换为LocalDate时,日期是否有可能翻转到下一天或前一天?我真的不想因时区问题而导致我的生日改变。 - Gert-Jan
1
@Gert-Jan 转换 toLocalDate() 等只是委托给已弃用的方法,如 date.getYear(),使用本地时区中午(根据 JDBC 所需和指定的要求),请参见源代码。如果您尝试一个无效的本地时间,由于 DST 更改而不存在,则可能会观察到一些奇怪的时间向前跳跃(主要涉及 TIME 和 TIMESTAMP 类型)。否则,只要您有一个严格遵守规范的 JDBC 驱动程序,即在本地 tz 中解释转换,转换就应该是安全的。 - Meno Hochschild
嗯...使用午夜?如果那天的日期没有午夜怎么办? - Hakanai
如果由于标准时间和夏令时之间的差距而导致午夜不存在,则时间通常会向前跳跃相应的差距大小。这是旧版Java以及新的java.time类的标准行为。例如:美洲/圣保罗将不会在今年10月15日看到午夜,因此当天最早的本地时间将是上午1点。 - Meno Hochschild
实际上,java.time通过调用方法atStartOfDay完全避开了这个问题,因此它的作用是毋庸置疑的,而包括“午夜”在内的措辞总是让我感到困惑。 - Hakanai
@Trejkaz 请参阅javadoc。然而,如何实现冬夏转换的确切细节是不可配置的(曾经计划过,但在JSR-310的开发过程中被放弃了)。 - Meno Hochschild

28

今天,我们大多数人都在使用符合JDBC 4.2标准的驱动程序,与2015年的答案相比,这在很大程度上改善了情况。

从结果集中获取LocalDate

LocalDate dateFromDatabase = yourResultSet.getObject(yourColumnIndex, LocalDate.class);

或者

LocalDate dateFromDatabase = yourResultSet.getObject("yourColumnLabel", LocalDate.class);

并没有为了这个而向 ResultSet 中添加新的方法。一直以来都有 getObject 方法。新的变化是,自从 JDBC 4.2 开始,它可以接受 LocalDate.class 作为第二个参数,并返回一个 LocalDate 对象。上述情况适用于查询返回 SQL 数据类型为 date 的列(实际上,JDBC 类型才是最重要的,但它们往往是一致的)。

您也可以传递其他 Java.time 类型的类,并获得相应的类型返回。例如:

OffsetDateTime dateTimeFromDatabase
        = yourResultSet.getObject(yourTimestampWithTimeZoneColumnIndex, OffsetDateTime.class);

应使用的 java.time 类型为:

SQL datatype            | java.time type
------------------------+-----------------------------------------------------------
date                    | LocalDate
time                    | LocalTime
timestamp               | LocalDateTime
timestamp with timezone | Officially OffsetDateTime; many drivers accept Instant too
time with timezone      | OffsetTime

如果要从Java传递参数到数据库(用于查询参数或存储),则PreparedStatement.setObject现在也接受上述java.time类型的对象。由于您正在传递类型的对象,因此在执行此操作时无需单独的类型参数。


25

关于Timestamp的新方法

Java 8在java.sql.Timestamp类中添加了一些新方法,用于转换成和从java.time对象中获取。这些便捷方法是一种临时措施,直到JDBC驱动程序可以更新为新的数据类型。

DateTime也是如此

在Java 8中,java.sql.Datejava.sql.Time类也添加了类似的java.time转换方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接