Spring JPA使用@Query查询DB2两个TIMESTAMP区间数据无返回问题
解决方案
首先你遇到的问题核心是时区不匹配、参数类型映射不明确两类原因,按以下步骤逐一排查即可解决:
1. 明确JPQL参数的类型映射与绑定
你当前Repository方法缺少参数绑定注解和时间类型声明,先调整方法定义:
@Repository // 注意JpaRepository第二个泛型是实体类的主键类型,不要误写为Timestamp,需要和你CarEntity的主键类型对齐,比如Long public interface CarRepository extends JpaRepository<CarEntity, Long>{ @Query("select c from CarEntity c where c.carModel = 'Toyota' and c.soldDate between :startDate and :endDate") List<CarEntity> getCarsSoldBetween( @Param("startDate") @Temporal(TemporalType.TIMESTAMP) Date startDate, @Param("endDate") @Temporal(TemporalType.TIMESTAMP) Date endDate ); }
- 补充
@Param注解明确绑定参数名,避免低版本Spring Data JPA参数绑定错位 - 补充
@Temporal(TemporalType.TIMESTAMP)声明参数是时间戳类型,和实体类字段、DB字段类型对齐
2. 统一应用与数据库的时区(核心问题)
从你打印的绑定日志可以看到参数时区是PDT,而你在DB2 Bench中执行SQL时用的是DB2服务端的时区,DB2的TIMESTAMP类型本身不带时区信息,两边时区不一致会导致实际传入的时间戳数值和你预期的字符串时间不匹配。
在application.properties中添加配置,强制Hibernate使用和DB2服务端一致的时区:
# 替换为你DB2服务端实际使用的时区,比如UTC、Asia/Shanghai等 spring.jpa.properties.hibernate.jdbc.time_zone=UTC
也可以在Spring Boot启动类中全局设置应用时区:
@SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } @PostConstruct public void initTimeZone() { // 统一时区为DB2使用的时区 TimeZone.setDefault(TimeZone.getTimeZone("UTC")); } }
3. 修正时间戳转换逻辑
你从URL拿到的是秒级时间戳,而Java的Date、Timestamp构造函数接收的是毫秒级时间戳,转换时需要乘以1000,否则会生成1970年的错误时间:
// 控制器中转换逻辑示例 Timestamp start = new Timestamp(startTimeStamp * 1000); Timestamp end = new Timestamp(endTimeStamp * 1000);
调整后也可以直接将Timestamp类型参数传给Repository,无需使用Date类型,进一步避免类型转换问题:
// Repository方法调整为直接接收Timestamp参数 List<CarEntity> getCarsSoldBetween(@Param("startDate") Timestamp startDate, @Param("endDate") Timestamp endDate);
4. 备选方案:使用命名查询简化实现
不需要写JPQL,直接用Spring Data JPA的命名规则生成查询,降低手写JPQL的出错概率:
List<CarEntity> findByCarModelAndSoldDateBetween(String carModel, Timestamp startDate, Timestamp endDate); // 调用时传参传入固定值"Toyota"和起止时间即可
内容的提问来源于stack exchange,提问作者pixel
相关产品推荐
相关产品推荐

