INTERVAL DAY TO SECOND 能不能直接用 java.time.Duration 接收?

能,但必须绕过 jdbc 默认行为——jdbc 驱动(如 ojdbc8)不支持直接 rs.getobject("col", duration.class),会抛 sqlfeaturenotsupportedexception。它底层返回的是 oracle.sql.intervalds 实例,而标准 jdbc api 没有定义到 duration 的映射契约。

为什么 @Temporal 和 java.util.Date 会失败?

@Temporal 只适用于 DATE、TIMESTAMP 等时间点类型,不是为持续时间设计的。INTERVAL DAY TO SECOND 是“长度”,不是“时刻”。驱动在调用 getTimestamp() 或 getTime() 时发现列类型是 INTERVALDS,就直接报错:Invalid column type: getTime not implemented for class oracle.jdbc.driver.T4CIntervaldsAccessor。

别尝试用 java.sql.Time、java.util.Calendar 或 LocalDateTime 强转也别依赖 Hibernate 自动识别——Hibernate 4/5 默认不处理 INTERVAL,除非显式注册自定义 UserType

安全可靠的读取方式:手动转换 oracle.sql.INTERVALDS → Duration

核心思路是:先用 rs.getObject("col") 拿到原生 oracle.sql.INTERVALDS,再调它的 toJdbc() 得到 long(纳秒总数),最后传给 Duration.ofNanos()。

示例代码:

Object raw = rs.getObject("DELIVERY_PERIOD");if (raw instanceof oracle.sql.INTERVALDS) { long nanos = ((oracle.sql.INTERVALDS) raw).toJdbc(); // 注意:返回值是纳秒数 Duration duration = Duration.ofNanos(nanos);}必须引入 Oracle JDBC 驱动的完整包(如 ojdbc8.jar),否则编译不过 oracle.sql.INTERVALDStoJdbc() 返回的是总纳秒数(正负都支持),和 Duration 的构造逻辑完全对齐如果字段允许 NULL,raw 可能为 null,记得判空不要用 toString() 解析,字符串格式依赖 NLS 设置,不可靠

JPA/Hibernate 场景下怎么映射?

不能只靠 @Column 或 @Convert。需要实现 org.hibernate.usertype.UserType(Hibernate 5)或 org.hibernate.type.descriptor.java.JavaType + SqlTypeDescriptor(Hibernate 6),并在注册时绑定到 INTERVAL DAY TO SECOND 列类型。

立即学习“Java免费学习笔记(深入)”;

最简实践路径:

在实体类中声明字段为 private Duration deliveryPeriod;写一个 IntervalDsToDurationType 实现 UserType<Duration>重写 nullSafeGet():按上一节逻辑从 INTERVALDS 构造 Duration重写 nullSafeSet():把 Duration.toNanos() 传给 PreparedStatement.setObject(idx, new INTERVALDS(conn, nanos))用 @Type(type = "IntervalDsToDurationType") 标注字段

真正容易被忽略的是:这个映射只在你**控制 PreparedStatement 和 ResultSet 流程**时才稳定;一旦用了 Spring Data JPA 的自动查询(如 findByXxx()),必须确保底层 JdbcTemplate 或 EntityManager 的方言/类型注册已生效,否则仍会 fallback 到字符串。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。