JPA传递自定义参数列表报错:无法识别参数类类型
问题分析与解决方案
你的代码存在几个关键问题,导致了类型解析错误:
- 原生SQL表别名错误:给
PEOPLE表起的别名是p,但查询条件里误用了s.firstName,应改为p.firstName。 - JPA原生查询无法直接解析自定义对象列表作为
IN参数:IN子句需要单一类型的集合(如字符串列表),JPA无法自动拆解PersonSearchParam对象为SQL可识别的字段值。 - Kotlin数据类命名不规范:类名应首字母大写,需改为
PersonSearchParam。
方案一:使用JPQL实现多条件组合匹配
JPQL支持直接访问自定义对象的属性,适合按「id+firstName+lastName」组合匹配的场景,代码简洁且无数据库语法依赖:
修正后的Repository方法
@Query(""" SELECT p FROM Person p WHERE (p.id, p.firstName, p.lastName) IN (SELECT param.id, param.firstName, param.lastName FROM :personSearchParams param) """) fun findBySearchParams(@Param("personSearchParams") personSearchParams: List<PersonSearchParam>): List<Person>
规范后的数据类
data class PersonSearchParam ( @NotBlank(message = "id must not be blank.") var id: String, @NotBlank(message = "firstName must not be blank.") var firstName: String, @NotBlank(message = "lastName must not be blank.") var lastName: String )
方案二:使用原生SQL(需适配数据库语法)
如果必须使用原生SQL,需将自定义对象列表拆解为三个独立字段集合,再通过组合字段匹配。不同数据库语法略有差异:
PostgreSQL版本
@Query(nativeQuery = true, value = """ SELECT * FROM PEOPLE p WHERE (p.id, p.first_name, p.last_name) IN ( SELECT unnest(:ids), unnest(:firstNames), unnest(:lastNames) ) """) fun findBySearchParams( @Param("ids") ids: List<String>, @Param("firstNames") firstNames: List<String>, @Param("lastNames") lastNames: List<String> ): List<Person>
调用时从参数列表提取对应集合:
val searchParams: List<PersonSearchParam> = // 你的参数列表 val ids = searchParams.map { it.id } val firstNames = searchParams.map { it.firstName } val lastNames = searchParams.map { it.lastName } val result = personRepository.findBySearchParams(ids, firstNames, lastNames)
MySQL版本(8.0.19+)
MySQL 8.0.19+支持VALUES语法构造临时数据集:
@Query(nativeQuery = true, value = """ SELECT p.* FROM PEOPLE p JOIN ( SELECT * FROM ( VALUES <foreach collection="personSearchParams" item="param" separator=","> (#{param.id}, #{param.firstName}, #{param.lastName}) </foreach> ) AS temp (id, first_name, last_name) ) AS search ON p.id = search.id AND p.first_name = search.first_name AND p.last_name = search.last_name """) fun findBySearchParams(@Param("personSearchParams") personSearchParams: List<PersonSearchParam>): List<Person>
关键注意事项
- 优先选择JPQL方案,避免数据库语法依赖,代码更易维护。
- 确保
Person实体类的字段与数据库表字段映射正确(如firstName对应first_name)。
内容的提问来源于stack exchange,提问作者Tasmon8
相关产品推荐
相关产品推荐

