Spring Data JPA动态列名查询报错:缺少':query%'命名参数
问题分析:Spring Data JPA动态查询参数异常原因
问题代码
interface CustomFooRepository { fun findByValueIgnoreCase(query: String, type: RequestType): List<Foo> } class CustomFooRepositoryImpl( @PersistenceContext private val entityManager: EntityManager ) : CustomFooRepository { override fun findByValueIgnoreCase(query: String, type: RequestType): List<Foo> { val column = when (type) { RequestType.first_name -> "first_name" RequestType.last_name -> "last_name" RequestType.email -> "email" } val sql = """ SELECT *, SIMILARITY(:column, :query) AS score FROM foo WHERE :column iLIKE %:query% ORDER BY score DESC NULLS LAST, :column LIMIT 20; """ val constructedQuery = entityManager.createNativeQuery(sql, Foo::class.java) constructedQuery.setParameter("column", column) constructedQuery.setParameter("query", query) return constructedQuery.resultList as List<Foo> } } interface FooRepository : JpaRepository<Foo, Long>, CustomFooRepository
运行异常
org.springframework.dao.InvalidDataAccessResourceUsageException: No argument for named parameter ':query%'
异常原因
- 通配符写法错误:SQL里的
%:query%会被JPA识别成一个名为:query%的完整参数,而不是:query参数加上通配符。JPA找不到这个不存在的参数,直接抛出异常。 - 动态列名不能用参数绑定:代码里用
:column绑定列名是无效的,JPA的参数绑定只支持值类型(比如字符串、数字),不支持列名、表名这类SQL标识符。实际执行时会把:column替换成字符串值(比如'first_name'),导致SQL逻辑变成WHERE 'first_name' iLIKE ...,完全不符合预期。排序字段:column也存在同样的问题。
修正思路
- 处理通配符:把通配符拼到参数值里,而不是SQL语句中。比如:
对应的SQL改成val wrappedQuery = "%$query%" constructedQuery.setParameter("query", wrappedQuery)WHERE ... iLIKE :query - 动态列名字符串拼接:因为
RequestType是枚举,不存在SQL注入风险,可以直接把列名拼到SQL中:val sql = """ SELECT *, SIMILARITY($column, :query) AS score FROM foo WHERE $column iLIKE :query ORDER BY score DESC NULLS LAST, $column LIMIT 20; """
内容的提问来源于stack exchange,提问作者four-eyes
相关产品推荐
相关产品推荐

