Hibernate 异常 “QueryParameterException: No Argument for Ordinal Parameter”

1、概览

本文将带你了解 Hibernate 出现 QueryParameterException: “no argument for ordinal parameter” 异常的原因以及解决办法。

2、理解异常

通常,Hibernate 会抛出 QueryParameterException 来提示查询参数出现问题。它表示指定的参数无效或未找到。

此外,“no argument for ordinal parameter(没有设置指定顺序的参数)” 消息表示 Hibernate 无法为定义的参数找到合适的参数。导致这种异常的常见原因是在 Hibernate 查询中忘记了为已定义的参数提供值。

3、实际案例

知道了 Hibernate 出现 QueryParameterException 异常的原因后,让我们通过一个实际的例子来看看如何重现它。

首先,来看看 Employee 实体类:

@Entity
public class Employee {
    @Id
    private int id;
    private String firstName;
    private String lastName;

    // 标准的 Getter 和 Setter
}

如上,EmployeeidfirstNamelastName 字段。

@Entity 注解用于指定 Employee 类是一个 JPA 实体,而 @Id 注解则标记了表示主键的字段。

接着,创建一个包含两个参数的 HQL 查询,并假装忘记为第二个参数指定值:

@Test
void whenMissingParameter_thenThrowQueryParameterException() {
    assertThatThrownBy(() -> {
       String selectQuery = """
           FROM Employee 
           WHERE firstName = ?1 
           AND lastName = ?2
        """;
        Query<Employee> query = session.createQuery(selectQuery, Employee.class);
        query.setParameter(1, "Jean");

        query.list();
    }).isInstanceOf(QueryParameterException.class)
      .hasMessageContaining("No argument for ordinal parameter");
}

可以看到,Hibernate 抛出了异常,因为我们没有使用 setParameter()lastName 参数设置值。

4、修复异常

解决 QueryParameterException 的最简单方法就是在执行查询之前为第二个参数指定一个有效值。

添加一个新的测试用例,并使用 setParameter() 设置姓氏:

@Test
void whenDefiningAllParameters_thenCorrect() {
   String selectQuery = """
       FROM Employee 
       WHERE firstName = ?1 
       AND lastName = ?2
    """;
    Query<Employee> query = session.createQuery(selectQuery, Employee.class);
    query.setParameter(1, "Jean")
      .setParameter(2, "Smith");

    assertThat(query.list()).isNotNull();
}

不出所料,测试用例成功执行,没有出现 QueryParameterException 异常。

5、总结

本文介绍了导致 Hibernate 出现异常 QueryParameterException: “no argument for ordinal parameter” 的原因,以及如何修复该异常。


Ref:https://www.baeldung.com/hibernate-fix-queryparameterexception