Spring Data JPA按日期区间查询Tender实体返回0条记录排查
我定义了如下Tender实体:
public class Tender { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(nullable = false, updatable = false) private Long id; private String source; private String sourceRefNumber; private String link; private String title; @Column(columnDefinition="TEXT") private String description; private String field; private String client; private String type; private Date date; private Date deadline; @ManyToMany private List<Cpv> cpv; }
并创建了对应的Repository接口:
public interface TenderRepository extends JpaRepository<Tender, Long> { List<Tender> findAllByDateGreaterThanEqualAndDateLessThanEqual(Date start, Date end); List<Tender> findAllByDateBetween(Date start, Date end); }
我在Service及ServiceImpl中使用该接口,同时在Resource层编写了如下方法:
@GetMapping("/listforperiod/{start}/{end}") public ResponseEntity<List<Tender>> getTendersForPeriod(@PathVariable("start") @DateTimeFormat(pattern = "yyyy-MM-dd") Date start, @PathVariable("end") @DateTimeFormat(pattern = "yyyy-MM-dd") Date end) { List<Tender> list = tenderService.findAllByDateBetween(start, end); return new ResponseEntity<>(list, OK); }
尝试上述两种查询方法后,均返回0条记录,但数据库中明明存在对应数据,请问问题可能出在哪里?
日期时间精度不匹配:
java.util.Date包含时分秒信息,你通过@DateTimeFormat解析的日期默认时分秒为00:00:00。如果数据库中date字段的记录带有非0的时分秒(比如2024-05-20 14:30:00),那么查询end为2024-05-20时,实际是查询<= 2024-05-20 00:00:00的记录,自然匹配不到。
解决办法:- 把
end日期调整为end日期+1天-1秒,覆盖当天所有时刻的记录; - 改用
LocalDate类型映射数据库日期字段,同时将Repository方法参数和Controller的日期解析改为LocalDate,彻底规避时分秒的干扰。
- 把
时区不一致:应用程序和数据库的时区可能不匹配,比如应用用UTC时区,数据库存东八区时间,导致日期解析后偏移,查询范围出错。
解决办法:- 统一两者时区,比如在配置文件中设置
spring.jpa.properties.hibernate.jdbc.time_zone=UTC(根据实际时区调整); - 检查数据库表
date字段的时区设置,确保和应用一致。
- 统一两者时区,比如在配置文件中设置
JPA查询边界处理差异:
findAllByDateBetween在部分JPA实现中是包含起始日期、排除结束日期的逻辑,如果数据库记录刚好是结束日期的0点,会被排除在外。
解决办法:改用findAllByDateGreaterThanEqualAndDateLessThanEqual并手动调整结束日期范围,或者开启SQL日志查看生成的查询语句,确认边界条件是否符合预期。SQL生成异常:开启JPA的SQL日志,查看实际执行的SQL语句,确认查询条件和参数是否正确。配置方式如下:
spring.jpa.show-sql=true spring.jpa.properties.hibernate.format_sql=true通过日志可以直观看到日期参数是否和你传入的一致,是否存在绑定错误。
实体字段映射错误:检查
Tender类的date字段是否正确映射到数据库的对应列,比如是否存在字段名和列名不匹配(数据库列是tender_date但实体字段是date且未加@Column指定)。
解决办法:给date字段添加@Column(name = "你的数据库列名"),确保映射关系正确。
内容的提问来源于stack exchange,提问作者Daniil Peterson

