You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用@Query搭配LocalDate参数查询抛出SQLGrammarException问题求助

问题原因分析
  • 核心诱因1:author字段的LIKE拼接写法错误,直接写%:#{#filter.author}%会将%识别为独立的查询片段,引发参数绑定错位,原本应该对应DATE类型的参数位置被其他类型参数占用,PostgreSQL无法匹配到预期的日期类型。
  • 核心诱因2:PostgreSQL无法自动识别SpEL表达式返回的LocalDate参数的数据类型,在is null判断分支中没有明确的类型上下文提示,进一步触发类型判定失败的错误。
可行解决方案

方案1:修正JPQL写法(成本最低,无需调整现有结构)

修正LIKE通配符拼接逻辑,同时显式指定日期参数类型,修改后的Repository查询代码如下:

@Query("SELECT r "
        + " FROM ResearchRequestEntity r "
        + " WHERE "
        + " (:#{#filter.content} is null OR r.content = :#{#filter.content}) AND "
        + " (:#{#filter.author} is null OR r.author LIKE CONCAT('%', :#{#filter.author}, '%')) AND "
        + " (:#{#filter.createdOn} is null OR r.createdOn <= CAST(:#{#filter.createdOn} AS java.time.LocalDate)) AND "
        + " (:#{#filter.status} is null OR r.status = :#{#filter.status})"
)
Page<ResearchRequestEntity> findByFilter(FilterDto filter, Pageable pageable);

修改点说明:

  1. 用CONCAT函数拼接模糊查询通配符,避免通配符和参数拆分导致的绑定错位
  2. 用CAST显式将SpEL返回的日期参数转换为LocalDate类型,给PostgreSQL明确的类型提示

方案2:改用JPA Specification实现动态查询(可维护性更高)

如果后续筛选条件会频繁迭代,推荐用Specification实现动态查询,从根源上避免SpEL参数绑定的各类问题:

  1. 首先让Repository接口继承JpaSpecificationExecutor<ResearchRequestEntity>
  2. 编写筛选条件构造逻辑:
public static Specification<ResearchRequestEntity> buildFilterSpec(FilterDto filter) {
    return (root, query, cb) -> {
        List<Predicate> predicates = new ArrayList<>();
        if (filter.getContent() != null) {
            predicates.add(cb.equal(root.get("content"), filter.getContent()));
        }
        if (filter.getAuthor() != null) {
            predicates.add(cb.like(root.get("author"), "%" + filter.getAuthor() + "%"));
        }
        if (filter.getCreatedOn() != null) {
            predicates.add(cb.lessThanOrEqualTo(root.get("createdOn"), filter.getCreatedOn()));
        }
        if (filter.getStatus() != null) {
            predicates.add(cb.equal(root.get("status"), filter.getStatus()));
        }
        return cb.and(predicates.toArray(new Predicate[0]));
    };
}
  1. 调用时直接使用内置查询方法即可:
Page<ResearchRequestEntity> result = repository.findAll(buildFilterSpec(filter), pageable);

内容的提问来源于stack exchange,提问作者Newboz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 09:15:03