JPQL查询返回0但对应SQL在MySQL执行正常,求助排查
解决Hibernate查询结果与MySQL直接执行不一致的问题
看起来你遇到了一个典型的Hibernate日期参数匹配问题,我来帮你一步步排查和解决:
首先,先锁定核心排查方向
你的代码逻辑本身没问题,但Hibernate返回结果和MySQL直接执行不一致,大概率是日期处理的细节差异导致的,我们从以下几个点入手:
1. 检查时区一致性问题
这是最常见的原因:Hibernate(JVM)的时区和MySQL的时区不一致,导致日期参数被转换后出现偏差。
- 先查看MySQL的时区:执行
SELECT @@global.time_zone, @@session.time_zone; - 再查看JVM的时区:可以在代码里加一行
System.out.println(TimeZone.getDefault().getID()); - 如果两者不一致,在Hibernate配置中添加时区统一配置:
hibernate.jdbc.time_zone=Asia/Shanghai # 替换成你的MySQL时区
2. 修正日期参数的传递方式
你用Calendar.getTime()返回的是带时间部分的Date对象,而数据库中dtentrega可能是DATE类型(仅存日期,无时间),Hibernate可能会自动补全时间,导致条件匹配偏差。建议改用Java 8+的日期API并明确指定时间类型:
public Integer getNumServicosEmAtraso() { try { // 用LocalDate只处理日期,避免时间干扰 LocalDate date = LocalDate.now().minusDays(2); // 注意JPQL中的属性名要和实体类Servico的属性完全一致(驼峰匹配) String jpql = "select count(s) from Servico s where (s.indtemlaudo = false or s.indtemlaudo IS NULL) AND s.dtEntrega <= :date AND s.dtEntradaRecoleta IS NOT NULL "; Query query = entityManager.createQuery(jpql); // 明确指定参数为DATE类型,避免自动转换问题 query.setParameter("date", date, TemporalType.DATE); return ((Long) query.getSingleResult()).intValue(); } catch (Exception e) { log.error("Erro no getNumServicosEmAtraso", e); } return -1; }
3. 验证Hibernate生成的实际SQL和参数
开启Hibernate的SQL日志(添加hibernate.show_sql=true到配置),查看生成的SQL和参数值是否和你手动在MySQL执行的完全一致。比如:
- 检查JPQL中的属性名是否和实体类
Servico的属性一致(比如你写的s.dtentrega,实体类里是不是dtEntrega?JPQL是基于实体类属性名,不是数据库字段名) - 查看日志中日期参数的实际值,是否和你手动传入的
2018-01-03一致,有没有被时区转换修改
4. 检查实体类字段映射
确认Servico类中dtEntrega的映射是否正确:
// 如果数据库是DATE类型,推荐用LocalDate映射 @Column(name = "dtentrega") private LocalDate dtEntrega; // 如果用Date的话,建议加上@Temporal注解明确类型 @Temporal(TemporalType.DATE) @Column(name = "dtentrega") private Date dtEntrega;
按照上面的步骤排查,应该能解决你的问题。如果还是不行,可以把Hibernate生成的SQL和实体类映射贴出来,我再帮你进一步分析。
内容的提问来源于stack exchange,提问作者jNewbie
相关产品推荐
相关产品推荐

