SpringBoot查询PostgreSQL TIMESTAMPTZ数据返回null问题排查
问题解决步骤
1. 修正实体类字段定义
PostgreSQL的TIMESTAMPTZ(带时区时间戳)需要对应Java8+的时区感知类型,java.util.Date是无时区的,无法正确映射该类型。修改实体类字段:
import java.time.OffsetDateTime; import javax.persistence.Column; import javax.persistence.Entity; @Entity public class MqttMessageParsed { // 其他字段... @Column(name = "datem", columnDefinition = "TIMESTAMPTZ") private OffsetDateTime datem; // getter、setter方法 }
2. 修正时间解析代码
SimpleDateFormat不支持解析时区偏移(如+00),会直接忽略该部分导致时间值错误。改用DateTimeFormatter解析OffsetDateTime:
import java.time.OffsetDateTime; import java.time.format.DateTimeFormatter; // 匹配带时区偏移的时间格式 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSX"); OffsetDateTime start = OffsetDateTime.parse("2022-07-24 10:11:29.452+00", formatter); OffsetDateTime end = OffsetDateTime.parse("2022-07-24 10:11:49.452+00", formatter); List<MqttMessageParsed> sensor_data = messageParsedRepository.findByCreatedAtBetween(start, end);
3. 修正Repository查询方法
将参数类型改为OffsetDateTime,确保时区信息正确传递到数据库查询:
import java.time.OffsetDateTime; import java.util.List; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.query.Param; public interface MqttMessageParsedRepository extends CrudRepository<MqttMessageParsed, Long> { @Query("SELECT t FROM MqttMessageParsed t WHERE t.datem BETWEEN :startDate AND :endDate") List<MqttMessageParsed> findByCreatedAtBetween(@Param("startDate") OffsetDateTime start, @Param("endDate") OffsetDateTime end); }
4. 添加时区统一配置
在application.properties中添加JPA时区配置,确保Hibernate与数据库时区一致:
spring.jpa.properties.hibernate.jdbc.time_zone=UTC spring.datasource.url=jdbc:postgresql://你的数据库地址:5432/数据库名?serverTimezone=UTC&useSSL=false
问题根源说明
java.util.Date无时区信息,映射TIMESTAMPTZ时会丢失时区偏移,导致数据库存储的时间与查询时间不在同一时区维度,无法匹配数据。SimpleDateFormat解析带+00的字符串时直接忽略时区,生成的Date为本地时区时间,与数据库中存储的UTC时间不匹配。
内容的提问来源于stack exchange,提问作者Ansif
相关产品推荐
相关产品推荐

