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
相关产品推荐
相关产品推荐

