Spring Boot多关键词模糊查询失效:含%字符无结果返回
Spring Boot PostgreSQL多关键词模糊查询问题解决
问题场景
需要实现多关键词模糊查询产品,比如搜索“wet food”时返回包含“wet”和“food”的产品(如“wet cat food”)。当前做法是将搜索词的空格替换为%,调用productRepository.findProductsByNameContainingIgnoreCase方法,但数据库存在匹配数据却始终返回空结果。直接编写SQL语句执行正常,但Spring Boot代码无法生效。
问题原因
Spring Data JPA的ContainingIgnoreCase系列方法会自动做两件事:
- 在参数前后添加
%通配符 - 将参数中自带的
%、_等通配符转义为普通字符(防止SQL注入)
所以当你传入处理后的wet%food时,实际生成的SQL条件是:
WHERE name ILIKE '%wet\%food%'
这里的\%是转义后的普通字符,不再作为通配符使用,导致无法匹配到包含“wet”和“food”的产品。
解决方案
方案1:自定义JPQL查询
直接编写JPQL语句,手动控制通配符的使用,避免JPA自动转义。
首先在Repository接口中定义自定义查询:
public interface ProductRepository extends JpaRepository<Product, Long> { @Query("SELECT p FROM Product p WHERE p.name ILIKE :searchPattern") List<Product> findProductsByNameMatching(@Param("searchPattern") String searchPattern); }
然后在业务层处理搜索词,将空格替换为%并前后添加%:
String searchTerm = "wet food"; // 转换为 %wet%food% 格式 String searchPattern = "%" + searchTerm.replace(" ", "%") + "%"; List<Product> products = productRepository.findProductsByNameMatching(searchPattern);
方案2:使用Specification动态构建查询
拆分搜索关键词,为每个关键词单独添加模糊查询条件,用AND连接,更灵活且避免通配符转义问题。
先编写Specification工具类:
public class ProductSpecifications { public static Specification<Product> nameContainsAllKeywords(String keywords) { return (root, query, criteriaBuilder) -> { // 按空格拆分关键词(支持多个连续空格) String[] keywordArray = keywords.split("\\s+"); Predicate[] predicates = new Predicate[keywordArray.length]; for (int i = 0; i < keywordArray.length; i++) { String keyword = keywordArray[i].toLowerCase(); // 为每个关键词添加模糊查询条件 predicates[i] = criteriaBuilder.like( criteriaBuilder.lower(root.get("name")), "%" + keyword + "%" ); } // 所有关键词条件必须同时满足 return criteriaBuilder.and(predicates); }; } }
然后调用Repository的findAll方法传入Specification:
List<Product> products = productRepository.findAll( ProductSpecifications.nameContainsAllKeywords("wet food") );
内容的提问来源于stack exchange,提问作者ElectroniQ
相关产品推荐
相关产品推荐

