Fixing Hibernate QueryParameterException: No Argument for Ordinal Parameter
This article will explore how to fix the Hibernate QueryParameterException: No Argument for Ordinal Parameter, understand its root cause, reproduce the error, and implement the correct solution with full code examples.
1. Understanding the Root Cause
When working with Hibernate, you might encounter the following exception: org.hibernate.QueryParameterException: No argument for ordinal parameter. This error occurs when Hibernate expects a value for a positional (ordinal) parameter but does not receive one. Ordinal parameters are referenced using a numerical index (?1
, ?2
, etc.), and Hibernate requires that each one be set before executing the query.
1.1 Common Causes
- Missing Parameter Binding – You referenced an ordinal parameter in the query but forgot to bind a value to it.
- Incorrect Indexing – Hibernate starts positional parameters from
1
, not0
. If you mistakenly use?0
, it can lead to this error. - Mismatched Parameter Count – The number of parameters in the query does not match the number of parameters bound in the code.
2. Reproducing the Exception
Here’s the Employee
entity class used in this article. This class is a JPA entity mapped to the database, with fields for id
, name
, salary
, and department
.
@Entity @Table(name = "employees") public class Employee { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(nullable = false) private String name; @Column(nullable = false) private double salary; @Column(nullable = false) private String department; public Employee() {} public Employee(String name, double salary, String department) { this.name = name; this.salary = salary; this.department = department; } // Getters and Setters }
Let’s see how this exception can be triggered.
public class HibernateQueryFix { public static void main(String[] args) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("EmployeePU"); EntityManager em = emf.createEntityManager(); try { em.getTransaction().begin(); // Incorrect query: Missing parameter binding String jpql = "FROM Employee e WHERE e.salary > ?1 AND e.department = ?2"; Query query = em.createQuery(jpql, Employee.class); // Only binding one parameter instead of two query.setParameter(1, 50000); // This will trigger the exception query.getResultList(); List<Employee> employees = query.getResultList(); for (Employee emp : employees) { System.out.println(emp); } em.getTransaction().commit(); } catch (Exception e) { e.printStackTrace(); em.getTransaction().rollback(); } finally { em.close(); emf.close(); } } }
This code demonstrates the incorrect use of positional parameters in a Hibernate JPQL query, leading to the QueryParameterException
. The query attempts to retrieve Employee
records where the salary is greater than ?1
and the department matches ?2
. However, while ?1
is correctly set using query.setParameter(1, 50000)
, the second parameter ?2
is missing. Hibernate expects all ordinal parameters to be set before executing the query, so failing to bind ?2
results in the QueryParameterException:
When we run this code, it throws:
3. Fixing the Exception
To fix this issue, ensure all ordinal parameters are correctly bound before executing the query.
Corrected Code:
public class HibernateQueryFix { public static void main(String[] args) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("EmployeePU"); EntityManager em = emf.createEntityManager(); try { em.getTransaction().begin(); String jpql = "FROM Employee e WHERE e.salary > ?1 AND e.department = ?2"; Query query = em.createQuery(jpql, Employee.class); // Binding both required parameters query.setParameter(1, 50000); query.setParameter(2, "Engineering"); query.getResultList(); List<Employee> employees = query.getResultList(); for (Employee emp : employees) { System.out.println(emp); } em.getTransaction().commit(); } catch (Exception e) { e.printStackTrace(); em.getTransaction().rollback(); } finally { em.close(); emf.close(); } } }
The fix involves ensuring that all query parameters are properly bound by setting values for both ?1
and ?2
. Hibernate requires positional parameters to be assigned correctly, starting from index 1
, so we use query.setParameter(1, 50000);
and query.setParameter(2, "Engineering");
to avoid errors. With all parameters properly set, the transaction commits successfully, and the query executes without triggering a QueryParameterExceptio
n.
4. Conclusion
In this article, we explored the root cause of Hibernate’s QueryParameterException
, demonstrated how to reproduce the error, and provided a clear solution to fix it. By ensuring that all positional parameters are correctly bound, we can avoid common query-related exceptions. Proper parameter handling not only prevents runtime errors but also enhances the reliability of Hibernate queries. With these best practices, we can write more error-free database queries in Hibernate.
5. Download the Source Code
This article covered how to fix the Hibernate QueryParameterException.
You can download the full source code of this example here: hibernate fix queryparameterexception