Spring JPA中ESCAPE关键字不识别启动报错问题排查
解决Spring Boot中@Query模糊查询的%转义与ESCAPE关键字异常问题
问题分析
启动时抛出antlr.NoViableAltException、提示unexpected token: ESCAPE,是因为Spring Data JPA的JPQL解析器不支持当前的ESCAPE用法;而之前%被转义导致无匹配结果,是因为参数中的%被当作普通字符串处理,没有作为模糊查询的通配符生效。另外你对ESCAPE的功能理解有误——它不是用来阻止%转义的,而是用来匹配字面量的%或_的。
解决方案
方案1:固定前后模糊匹配(服务层无需传%)
如果需求是固定的前后通配符查询,直接在JPQL里用CONCAT拼接%,避免参数带%导致转义:
@Repository public interface PostRepository extends JpaRepository<Post, Long> { @Query("SELECT p FROM Post p WHERE p.title LIKE CONCAT('%', :keyword, '%')") List<Post> findByTitleContaining(@Param("keyword") String keyword); }
调用时只需传入关键词(比如"test"),JPQL会自动拼接前后%,此时SQL输出的%是静态部分,不会被转义,能正常作为通配符使用。
方案2:灵活传入通配符(支持自定义%、_位置)
如果需要服务层自由控制通配符位置(比如传"test%"或"%test"),可以用以下两种方式:
方式A:使用原生SQL
直接写原生SQL,绕过JPQL的参数转义逻辑:
@Repository public interface PostRepository extends JpaRepository<Post, Long> { @Query(value = "SELECT * FROM post WHERE title LIKE ?1", nativeQuery = true) List<Post> findByTitleLike(String keyword); }
调用时直接传入带通配符的参数(比如"%test%"),原生SQL会直接识别参数中的%作为通配符。
方式B:JPQL中使用SpEL表达式
利用Spring Data JPA的SpEL支持,直接将参数作为原始字符串传入JPQL:
@Repository public interface PostRepository extends JpaRepository<Post, Long> { @Query("SELECT p FROM Post p WHERE p.title LIKE :#{#keyword}") List<Post> findByTitleLike(@Param("keyword") String keyword); }
这种方式会跳过JPQL对参数的转义处理,参数中的%会直接作为通配符生效。
正确使用ESCAPE的场景
ESCAPE是用来处理**需要匹配字面量%或_**的场景,比如要查询标题中包含"5%"的内容:
@Repository public interface PostRepository extends JpaRepository<Post, Long> { @Query("SELECT p FROM Post p WHERE p.title LIKE :keyword ESCAPE '\\'") List<Post> findByTitleWithPercent(@Param("keyword") String keyword); }
调用时传入参数"%5\%%"——这里的\是指定的转义字符,告诉JPA第二个%是字面量,不是通配符。
内容的提问来源于stack exchange,提问作者Baba
相关产品推荐
相关产品推荐

