Spring Data JPA 3中@CreatedDate无法填充OffsetDateTime字段的解决方法
问题背景
在Spring Boot 3应用中集成Spring Data JPA审计功能,使用@CreatedDate和@LastModifiedDate注解,但OpenAPI Generator自动生成的实体类中日期时间属性为java.time.OffsetDateTime类型,测试时报错提示仅支持java.util.Date、java.lang.Long、long类型,与官方文档支持JDK8日期类型的描述不符。
报错信息
Test shouldCreateANewGatewayPCWithNullLocationName() FAILED (1.2s) jakarta.servlet.ServletException: Request processing failed: org.springframework.dao.InvalidDataAccessApiUsageException: Invalid date type class com.hht.extope.restella.generated.model.GatewayPc for member class GatewayPc { id: null name: gatewayPcName locationName: null timezoneId: 0 createdAt: null updatedAt: null }; Supported types are [java.util.Date, java.lang.Long, long] at app//com.hht.extope.restella.controller.gatewaypc.GatewayPcControllerTest.shouldCreateANewGatewayPCWithNullLocationName(GatewayPcControllerTest.java:626) Caused by: org.springframework.dao.InvalidDataAccessApiUsageException: Invalid date type class com.hht.extope.restella.generated.model.GatewayPc for member class GatewayPc { id: null name: gatewayPcName locationName: null timezoneId: 0 createdAt: null updatedAt: null }; Supported types are [java.util.Date, java.lang.Long, long] at app//com.hht.extope.restella.controller.gatewaypc.GatewayPcControllerTest.shouldCreateANewGatewayPCWithNullLocationName(GatewayPcControllerTest.java:626) Caused by: java.lang.IllegalArgumentException: Invalid date type class com.hht.extope.restella.generated.model.GatewayPc for member class GatewayPc { id: null name: gatewayPcName locationName: null timezoneId: 0 createdAt: null updatedAt: null }; Supported types are [java.util.Date, java.lang.Long, long] at com.hht.extope.restella.controller.gatewaypc.GatewayPcControllerTest.shouldCreateANewGatewayPCWithNullLocationName(GatewayPcControllerTest.java:626)
问题分析
报错核心是Spring Data JPA审计模块未正确识别OffsetDateTime类型,默认日期处理器仅支持旧版日期类型,且出现了错误将实体类本身识别为日期字段的异常,需通过自定义配置让审计模块适配JDK8日期类型。
解决方案
1. 开启JPA审计并指定自定义日期提供器
在Spring Boot启动类添加@EnableJpaAuditing注解,指定自定义的日期提供器Bean:
@SpringBootApplication @EnableJpaAuditing(dateTimeProviderRef = "offsetDateTimeAuditingProvider") public class RestellaApplication { public static void main(String[] args) { SpringApplication.run(RestellaApplication.class, args); } }
2. 实现OffsetDateTime类型的日期提供器
创建一个DateTimeProvider实现类,返回当前UTC时区的OffsetDateTime,供审计模块使用:
@Component("offsetDateTimeAuditingProvider") public class OffsetDateTimeAuditingProvider implements DateTimeProvider { @Override public Optional<TemporalAccessor> getNow() { return Optional.of(OffsetDateTime.now(ZoneOffset.UTC)); } }
3. 完善实体类字段的JPA映射
为日期字段补充数据库列定义,确保JPA和数据库正确映射OffsetDateTime类型(以MySQL为例):
@JsonProperty("createdAt") @jakarta.persistence.Column(updatable = false, nullable = false, columnDefinition = "TIMESTAMP WITH TIME ZONE") @org.springframework.data.annotation.CreatedDate @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) private OffsetDateTime createdAt; @JsonProperty("updatedAt") @jakarta.persistence.Column(nullable = false, columnDefinition = "TIMESTAMP WITH TIME ZONE") @org.springframework.data.annotation.LastModifiedDate @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) private OffsetDateTime updatedAt;
4. 确认依赖版本兼容性
确保Spring Boot 3对应的Spring Data JPA(3.x)和Hibernate(6.x)版本正确引入,这两个版本原生支持JDK8日期时间类型,无需额外依赖。
验证
修改配置后重新运行测试,Spring Data JPA审计模块将自动为createdAt和updatedAt字段填充OffsetDateTime类型的时间值,不再出现类型不支持的报错。
内容的提问来源于stack exchange,提问作者Mirza Prangon

