Quarkus 2升级至3后Panache日期查询报错:LocalDate与String无法比较
从Quarkus 2升级到Quarkus 3后Panache查询失效问题解决
问题重现
实体类定义:
@Entity public class Cat extends Serializable { @Id @Column(unique = true, nullable = false) protected UUID id; private LocalDate electionDate; }
仓库查询方法:
@ApplicationScoped public class CatRepository implements PanacheRepository<Cat> { public Uni<Cat> findByElectionDate(){ return find("electionDate", "2024-01-07").firstResult(); } }
升级到Quarkus 3后触发错误:
Caused by: org.hibernate.query.SemanticException: Cannot compare left expression of type 'java.time.LocalDate' with right expression of type 'java.lang.String'
该查询在Quarkus 2版本可正常执行,使用electionDate = {d '2024-01-07'}的查询语句可正常工作,但需要前端大量适配。
问题原因
Quarkus 3升级了Hibernate ORM版本(从Hibernate 5.x升级到6.x),Hibernate 6对JPQL的类型校验更严格,不再允许字符串与LocalDate类型的隐式跨类型比较,而Quarkus 2依赖的Hibernate 5.x会自动处理这种隐式转换,导致升级后原有查询失效。
解决方案
1. 传递类型匹配的参数(推荐)
将查询参数转换为LocalDate类型后传入,无需修改查询语句,也不需要前端适配:
@ApplicationScoped public class CatRepository implements PanacheRepository<Cat> { public Uni<Cat> findByElectionDate(){ LocalDate targetDate = LocalDate.parse("2024-01-07"); return find("electionDate", targetDate).firstResult(); } }
如果参数由前端传入,直接接收LocalDate类型参数即可,Quarkus会自动完成参数绑定与类型转换。
2. 使用JPQL日期字面量(适配旧代码场景)
若无法修改参数类型,可使用JPQL标准的日期字面量格式{d 'yyyy-MM-dd'},但这种方式需要修改查询语句,会带来前端适配成本,仅建议在无法重构代码的场景下使用:
@ApplicationScoped public class CatRepository implements PanacheRepository<Cat> { public Uni<Cat> findByElectionDate(){ return find("electionDate = {d '2024-01-07'}").firstResult(); } }
3. 遵循JPQL规范编写查询
Hibernate 5.x的隐式类型转换属于非规范行为,Hibernate 6严格遵循JPQL规范,建议后续编写查询时始终保证参数与实体字段类型匹配,避免依赖非规范的隐式转换,提升代码的兼容性与可维护性。
内容的提问来源于stack exchange,提问作者Mikhail Kliman
相关产品推荐
相关产品推荐

