1. Overview
1.概述
In this short tutorial, we’ll shed light on how to solve the Hibernate QueryException: “named parameter not bound”.
在本简短教程中,我们将介绍如何解决 Hibernate QueryException:”命名参数未绑定”。
First, we’ll elucidate the main cause behind the exception. Then, we’ll demonstrate how to reproduce it, and finally, we’ll learn how to fix it.
首先,我们将阐明异常背后的主要原因。然后,我们将演示如何重现异常,最后,我们将学习如何修复异常。
2. Understanding the Exception
2.了解例外情况
Before jumping to the solution, let’s try to understand what the exception and its stack trace mean.
在跳转到解决方案之前,让我们先了解一下异常及其堆栈跟踪的含义。
In short, Hibernate throws QueryException to signal an error when translating a Hibernate query to SQL due to an invalid syntax. Therefore, the stack trace “named parameter not bound” indicates that Hibernate fails to bind a named parameter specified in a particular query.
简而言之,在将 Hibernate 查询转换为 SQL 时,由于语法无效,Hibernate 会抛出 QueryException 以发出错误信号。因此,堆栈跟踪 “named parameter not bound” 表明 Hibernate 无法绑定特定查询中指定的 命名参数。
Typically, a named parameter is prefixed with a colon (:) and followed by a placeholder for the actual value that needs to be set before executing the query:
通常情况下,命名参数的前缀是冒号(:),后面是一个占位符,表示在执行查询之前需要设置的实际值:
SELECT p FROM Person p WHERE p.firstName = :firstName;
One of the most common causes of our exception is forgetting to assign a value for a named parameter in a Hibernate query.
导致异常的最常见原因之一是忘记为 Hibernate 查询中的命名参数赋值。
3. Reproducing the Exception
3.复制例外
Now that we know what is the leading cause of the exception, let’s go down the rabbit hole and see how to reproduce it using a practical example.
既然我们已经知道导致异常的主要原因是什么,那就让我们通过一个实际的例子来看看如何重现异常。
First, let’s consider the Person entity class:
首先,让我们来看看 Person 实体类:
@Entity
public class Person {
@Id
private int id;
private String firstName;
private String lastName;
// standard getters and setters
}
Here, the @Entity annotation denotes that our class is an entity that maps a table in the database. Furthermore, @Id indicates that the id property represents the primary key.
在这里,@Entity 注解表示我们的类是一个实体,它映射了数据库中的一个表。此外,@Id 表示 id 属性代表主键。
Now, let’s create a Hibernate query with a named parameter and pretend to forget to set a value for our parameter:
现在,让我们创建一个带有命名参数的 Hibernate 查询,并假装忘记为参数设置值:
@Test
void whenNotSettingValueToNamedParameter_thenThrowQueryException() {
Exception exception = assertThrows(QueryException.class, () -> {
Query<Person> query = session.createQuery("FROM Person p WHERE p.firstName = :firstName", Person.class);
query.list();
});
String expectedMessage = "Named parameter not bound";
String actualMessage = exception.getMessage();
assertTrue(actualMessage.contains(expectedMessage));
}
As we can see, the test case fails with QueryException: “named parameter not bound”. The reason here is that Hibernate doesn’t know anything about the named parameter firstName and expects this parameter to be set before executing the query.
正如我们所见,测试用例以 QueryException:“named parameter not bound” 失败。原因是 Hibernate 不知道命名参数 firstName 的任何信息,并希望在执行查询之前设置该参数。
4. Fixing the Exception
4.修复异常
The solution to avoid QueryException in this case is to assign a value to the named parameter before executing the query. To do so, we can use the setParameter() method:
在这种情况下,避免 QueryException 的解决方案是在执行查询之前为命名的参数赋值。为此,我们可以使用 setParameter() 方法:
@Test
void whenSettingValueToNamedParameter_thenDoNotThrowQueryException() {
Query<Person> query = session.createQuery("FROM Person p WHERE p.firstName = :firstName", Person.class);
query.setParameter("firstName", "Azhrioun");
assertNotNull(query.list());
}
As shown above, the test case passes with success. The setParameter() call tells Hibernate which value to use for our named parameter when executing the query.
如上所示,测试用例成功通过。setParameter()调用告诉 Hibernate 在执行查询时使用哪个值作为命名参数。
5. Conclusion
5.结论
In this short article, we explained what causes Hibernate to throw QueryException: “named parameter not bound”. Then, we illustrated using a practical example how to reproduce the exception and how to fix it.
在这篇短文中,我们解释了 Hibernate 抛出 QueryException 的原因:”命名参数未绑定”。然后,我们用一个实际例子说明了如何重现异常以及如何修复异常。
As always, the full source code of the examples is available over on GitHub.
一如既往,示例的完整源代码可在 GitHub 上获取。