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

Spring Data JPA中如何用SPEL动态添加JPQL的WHERE子句

Spring Data JPA通过SPEL动态生成JPQL WHERE子句的解决方案

需求

刚学习Spring Data JPA,需要实现:通过SPEL动态生成JPQL的WHERE子句。当请求参数对象GetSourceListRequest的category字段为空列表时,不添加WHERE过滤条件;当该列表非空时,添加WHERE ic.categoryId IN (:category)子句。

请求参数对象

data class GetSourceListRequest(
    val category: List<Int>,
    val text: String,
    val tag: List<Int>,
    val order: Sort.Direction,  
    val pageSize: Int,    
    val currentPage: Int
)

原错误写法

尝试直接通过SPEL拼接字符串生成WHERE子句,导致JPQL语法错误:

interface ISourceItemDao : JpaRepository<SourceItemEntity, Long>, CrudRepository<SourceItemEntity, Long> {
    @Query(
        """
        select e.id 
        from SourceItemEntity e
        left join SourceItemToCategoryEntity ic on e.id = ic.itemId
        #{#request.category.size() > 0 ? 'where ic.categoryId in (:#{#request.category})' : ''}
        """
    )
    fun getIdByCondition(request: GetSourceListRequest, pageable: Pageable): Page<Long>
}

关键错误代码

#{#request.category.size() > 0 ? 'where ic.categoryId in (:#{#request.category})' : ''}

错误原因:直接拼接字符串的方式会导致JPQL语法不合法,比如category为空时会出现多余的结构;同时SPEL表达式内部嵌套的参数写法存在解析问题,无法正确识别参数。

修正后代码

通过在WHERE子句中使用条件判断逻辑,实现动态过滤:

interface ISourceItemDao : JpaRepository<SourceItemEntity, Long>, CrudRepository<SourceItemEntity, Long> {
    @Query(
        """
        select e.id 
        from SourceItemEntity e
        left join SourceItemToCategoryEntity ic on e.id = ic.itemId
        where (:#{#request.category.isEmpty()} = true)
        or (:#{#request.category.isEmpty()} = false and ic.categoryId in (:#{#request.category})) 
        """
    )
    fun getIdByCondition(request: GetSourceListRequest, pageable: Pageable): Page<Long>
}

思路说明:

  • 当category为空列表时,(:#{#request.category.isEmpty()} = true)条件成立,WHERE子句等价于where true,不会对结果进行过滤
  • 当category非空时,执行ic.categoryId in (:#{#request.category})的过滤逻辑,通过and确保只有列表非空时才触发该条件

依赖配置

使用Spring Boot 3.0.4版本的Spring Data JPA依赖:

<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>3.0.4</version>
  <relativePath/> <!-- lookup parent from repository -->
</parent>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 15:50:44