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

JPA原生查询用citext时IN子句传字符串列表报错

解决方案

1. 修复参数绑定不匹配问题

你遇到的Named parameter not bound : ingredientFilter错误,核心原因是参数名称不匹配:

  • SQL查询里用的参数是:ingredientFilter
  • 但@Param注解指定的参数名是"ingredient"

两种修改方式二选一:

方式一:同步@Param的参数名

@Query(value = "select personal_recipes.name, personal_recipes.type, personal_recipes.comments, " +
        "personal_recipes.instructions, personal_recipes.rating, ingredients.name, ingredients.quantity " +
        "from personal_recipes " +
        "inner join ingredients on personal_recipes.name = ingredients.recipe_name " +
        "where (ingredients.name::citext in (:ingredientFilter))" , nativeQuery = true)
List<PersonalRecipesEntity> getPersonalRecipesByIngredient(@Param(value = "ingredientFilter") List<String> ingredientFilter);

方式二:同步SQL中的参数名

@Query(value = "select personal_recipes.name, personal_recipes.type, personal_recipes.comments, " +
        "personal_recipes.instructions, personal_recipes.rating, ingredients.name, ingredients.quantity " +
        "from personal_recipes " +
        "inner join ingredients on personal_recipes.name = ingredients.recipe_name " +
        "where (ingredients.name::citext in (:ingredient))" , nativeQuery = true)
List<PersonalRecipesEntity> getPersonalRecipesByIngredient(@Param(value = "ingredient") List<String> ingredientFilter);

2. 修复返回结果与实体类匹配问题

当前查询返回的是两张表的字段,但方法返回的是List<PersonalRecipesEntity>,如果实体类仅对应personal_recipes表,会出现字段不匹配的问题,可通过以下方式解决:

方式一:用DTO接收查询结果

定义一个DTO类来封装查询返回的所有字段:

// 自定义DTO类
public class RecipeIngredientDTO {
    private String recipeName;
    private String type;
    private String comments;
    private String instructions;
    private Integer rating;
    private String ingredientName;
    private String quantity;

    // 全参构造函数
    public RecipeIngredientDTO(String recipeName, String type, String comments, String instructions, Integer rating, String ingredientName, String quantity) {
        this.recipeName = recipeName;
        this.type = type;
        this.comments = comments;
        this.instructions = instructions;
        this.rating = rating;
        this.ingredientName = ingredientName;
        this.quantity = quantity;
    }

    // 按需添加getter方法
}

// 修改Repository方法的返回类型
@Query(value = "select personal_recipes.name, personal_recipes.type, personal_recipes.comments, " +
        "personal_recipes.instructions, personal_recipes.rating, ingredients.name, ingredients.quantity " +
        "from personal_recipes " +
        "inner join ingredients on personal_recipes.name = ingredients.recipe_name " +
        "where (ingredients.name::citext in (:ingredientFilter))" , nativeQuery = true)
List<RecipeIngredientDTO> getPersonalRecipesByIngredient(@Param(value = "ingredientFilter") List<String> ingredientFilter);

方式二:使用@SqlResultSetMapping映射结果

在PersonalRecipesEntity上定义结果集映射,让Hibernate知道如何映射多表字段:

@Entity
@SqlResultSetMapping(
    name = "RecipeIngredientMapping",
    classes = @ConstructorResult(
        targetClass = PersonalRecipesEntity.class,
        columns = {
            @ColumnResult(name = "name"),
            @ColumnResult(name = "type"),
            @ColumnResult(name = "comments"),
            @ColumnResult(name = "instructions"),
            @ColumnResult(name = "rating"),
            @ColumnResult(name = "ingredient_name"),
            @ColumnResult(name = "quantity")
        }
    )
)
public class PersonalRecipesEntity {
    // 实体类原有字段,需添加对应上述列的构造函数
    public PersonalRecipesEntity(String name, String type, String comments, String instructions, Integer rating, String ingredientName, String quantity) {
        // 给实体类字段赋值
        this.name = name;
        this.type = type;
        this.comments = comments;
        this.instructions = instructions;
        this.rating = rating;
        // 注意:如果实体类没有ingredientName和quantity字段,需添加对应字段
        this.ingredientName = ingredientName;
        this.quantity = quantity;
    }

    // 其他构造函数、字段、getter/setter
}

// 修改查询语句,给字段加别名并指定映射名
@Query(value = "select personal_recipes.name, personal_recipes.type, personal_recipes.comments, " +
        "personal_recipes.instructions, personal_recipes.rating, ingredients.name as ingredient_name, ingredients.quantity " +
        "from personal_recipes " +
        "inner join ingredients on personal_recipes.name = ingredients.recipe_name " +
        "where (ingredients.name::citext in (:ingredientFilter))" , 
        nativeQuery = true,
        resultSetMapping = "RecipeIngredientMapping")
List<PersonalRecipesEntity> getPersonalRecipesByIngredient(@Param(value = "ingredientFilter") List<String> ingredientFilter);

3. 确认citext扩展已启用

确保你的PostgreSQL数据库已经安装citext扩展,若未安装,执行以下SQL启用:

CREATE EXTENSION IF NOT EXISTS citext;

内容的提问来源于stack exchange,提问作者778899

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 23:20:38