使用原生Query查询枚举时遇Hibernate参数错误求助
解决Hibernate原生查询"Ordinal parameters did not start with base 1 : 2"错误
切换到原生查询后出现org.hibernate.QueryException: Ordinal parameters did not start with base 1 : 2错误,相关代码如下:
Repository代码
@Query(value= """ SELECT mi.* FROM meal_item AS mi WHERE (mi.meal LIKE '%?1%' OR mi.note LIKE '%?1%') AND (?2 IS NULL OR ?2 = mi.meal_size) """, nativeQuery=true) List<MealItem> getAllMealItems(String search, MealItem.MealSize mealSize, Pageable pageable);
Service代码
@Override public List<MealItem> getAllMealItems(String search, Pageable pageable) { return mealItemRepository.getAllMealItems(search, MealItem.MealSize.light, pageable); }
MealItem枚举及字段代码
public enum MealSize{ light, medium, heavy } @Enumerated(EnumType.STRING) @JsonProperty("size") @Column(name="meal_size", columnDefinition="ENUM('light','medium','heavy')", nullable=false) private MealSize mealSize;
错误原因
Hibernate处理带Pageable参数的原生查询时,会自动添加分页相关参数(如limit、offset),这会打乱手动指定的位置参数(?1、?2)索引顺序,导致参数索引匹配异常。同时直接在SQL字符串中拼接%?1%的写法不符合参数绑定规范,也可能引发其他问题。
解决方案
改用命名参数替代位置参数,配合@Param注解绑定方法参数,避免索引冲突;同时规范参数拼接方式:
修改后的Repository代码:
import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; // ... @Query(value= """ SELECT mi.* FROM meal_item AS mi WHERE (mi.meal LIKE CONCAT('%', :search, '%') OR mi.note LIKE CONCAT('%', :search, '%')) AND (:mealSize IS NULL OR :mealSize = mi.meal_size) """, nativeQuery=true) List<MealItem> getAllMealItems(@Param("search") String search, @Param("mealSize") MealItem.MealSize mealSize, Pageable pageable);
说明
- 命名参数
:search和:mealSize通过@Param注解与方法参数绑定,Hibernate能精准识别每个参数,不受Pageable带来的额外参数影响。 - 使用
CONCAT('%', :search, '%')替代'%?1%',既避免SQL注入风险,也符合Hibernate参数绑定规范。 - 枚举配置
@Enumerated(EnumType.STRING)已正确,Hibernate会自动将枚举值转换为对应字符串与数据库字段匹配。
内容的提问来源于stack exchange,提问作者wandering_scholar
相关产品推荐
相关产品推荐

