You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JPA传递自定义参数列表报错:无法识别参数类类型

问题分析与解决方案

你的代码存在几个关键问题,导致了类型解析错误:

  1. 原生SQL表别名错误:给PEOPLE表起的别名是p,但查询条件里误用了s.firstName,应改为p.firstName。
  2. JPA原生查询无法直接解析自定义对象列表作为IN参数:IN子句需要单一类型的集合(如字符串列表),JPA无法自动拆解PersonSearchParam对象为SQL可识别的字段值。
  3. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 19:52:44