SpringBoot集成Oracle数据库返回JSON时Timestamp格式异常排查求助
错误原因分析
你遇到的java.lang.IllegalArgumentException: Timestamp format must be yyyy-mm-dd hh:mm:ss[.fffffffff]错误,核心原因是JDBC驱动在转换Oracle DATE类型到Java对象时格式不匹配:
- 你的Oracle数据库存储的DATE是
dd/MM/yyyy格式(比如15/10/2020),但Java的Timestamp.valueOf()方法仅接受yyyy-MM-dd HH:mm:ss(或带纳秒的扩展格式)。 - 即使你加了
@JsonIgnore,JPA在查询数据时依然会加载这个字段,所以转换错误会在查询阶段就触发,而不是序列化阶段。
解决方案
方案1:使用Java 8+时间API适配日期类型(推荐)
Oracle的DATE如果仅存储日期部分,用java.time.LocalDate替代java.util.Date是最规范的选择,JPA 2.2+原生支持这个类型,不需要额外的注解配置:
@Entity @Table(name = "SIGNAL") public class Signal implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "SIG_MATR") private String sigMatr; private String sigSitu; private String sigSexe; @JsonIgnore // 若不需要返回该字段,保留此注解 private LocalDate sigDate; // 替换为LocalDate }
方案2:修正@Temporal注解匹配DATE类型
如果你必须使用java.util.Date,要确保@Temporal注解指定的是TemporalType.DATE(而非TIMESTAMP),因为Oracle DATE类型对应日期部分时,应该映射为DATE而非时间戳:
@Entity @Table(name = "SIGNAL") public class Signal implements Serializable { // 其他字段不变 @JsonIgnore @Temporal(TemporalType.DATE) // 关键:用DATE替代TIMESTAMP private Date sigDate; }
方案3:JDBC URL指定日期格式(针对特殊存储格式)
如果数据库中DATE确实包含时间,但存储格式是dd/MM/yyyy,可以在JDBC连接URL中添加格式参数,让驱动正确解析:
# application.properties spring.datasource.url=jdbc:oracle:thin:@//localhost:1521/ORCL?oracle.jdbc.dateFormat=dd/MM/yyyy&oracle.jdbc.timezoneAsRegion=false
注意:不同版本的Oracle JDBC驱动参数可能略有差异,请根据你的驱动版本调整。
方案4:完全排除该字段的加载
如果完全不需要读取sigDate字段,可以在Repository中定义自定义查询,只返回需要的字段:
// SignalRepository接口 public interface SignalRepository extends JpaRepository<Signal, String> { @Query("SELECT s.sigMatr, s.sigSitu, s.sigSexe FROM Signal s") Iterable<Object[]> findAllWithoutDate(); } // 控制器修改 @GetMapping("/all") public Iterable<Object[]> allCollab() { return dao.findAllWithoutDate(); }
也可以使用JPA投影(Projection)来更优雅地返回指定字段,避免加载不需要的字段。
验证建议
优先尝试方案1,因为Java 8+的时间API设计更合理,能避免很多旧日期API的坑。如果问题依旧,检查你的Oracle JDBC驱动版本是否与Spring Boot版本兼容(比如Spring Boot 2.x推荐使用ojdbc8)。
内容的提问来源于stack exchange,提问作者developer

