1. 概述

在使用 Hibernate 进行数据库操作时,我们通常会用到命名参数(named parameters)来动态构造查询语句。这种方式不仅能提升代码可读性,更重要的是✅能有效防止 SQL 注入攻击。

但在实际开发中,经常会遇到两个看似不同但本质相似的报错:

  • Not all named parameters have been set(原生 Hibernate)
  • Named parameter not bound(JPA 实现中常见)

虽然错误信息略有差异,但根本原因一致:你在执行查询前,漏掉了某个命名参数的赋值

本文将深入剖析这一常见“踩坑”点,并通过实际示例展示如何正确使用 Hibernate 的命名参数机制,避免这类低级但高频的问题。

🔍 本文示例基于 Hibernate 原生 API,但原理同样适用于 JPA 的 @QueryTypedQuery

2. 错误成因分析

核心原则很简单:每个命名参数都必须在查询执行前完成绑定,否则 Hibernate 直接抛异常。

来看一个典型出错场景:

Query<Event> query = session.createQuery("from Event E WHERE E.title = :eventTitle", Event.class);

上面这句 HQL 中,:eventTitle 就是一个命名参数(注意冒号前缀)。Hibernate 在解析时就知道这里需要一个外部传入的值。

但如果你忘了设置它,直接执行:

List<Event> listOfEvents = query.list();

结果就是——boom 💥:

org.hibernate.QueryException: Not all named parameters have been set

⚠️ 这个异常发生在 query.list() 调用时,说明 Hibernate 在执行前做了参数完整性校验。

3. 解决方案

解决方法简单粗暴:在执行前把参数填上。

使用 setParameter() 方法即可完成绑定:

Query<Event> query = session.createQuery("from Event E WHERE E.title = :eventTitle", Event.class);
query.setParameter("eventTitle", "Event 1");

assertEquals(1, query.list().size());

✅ 关键点:

  • 参数名传的是 "eventTitle",不需要加冒号
  • 类型自动推断,支持大多数常见类型(String、Long、Date 等)
  • 如果有多个参数,每个都得 setParameter 一遍

多参数示例(避免踩坑)

Query<Event> query = session.createQuery(
    "from Event E WHERE E.title = :title AND E.location = :location AND E.startTime > :startTime", 
    Event.class
);

query.setParameter("title", "Tech Conf 2024")
     .setParameter("location", "Shanghai")
     .setParameter("startTime", LocalDateTime.now());

List<Event> results = query.list();

📌 建议链式调用,代码更清晰,也不容易漏参数。

4. 总结

Named parameters 是 Hibernate 中非常基础但极易出错的功能。记住一句话就能避开 90% 的坑:

所有以 :xxx 形式出现的参数,执行前必须通过 setParameter("xxx", value) 绑定值。

这个机制虽然简单,但在复杂业务逻辑或动态拼接查询时特别容易遗漏,建议:

  • 开发时开启 Hibernate SQL 日志(show_sqllogging.level.org.hibernate.SQL=DEBUG),观察实际生成的 SQL
  • 单元测试务必覆盖参数绑定场景
  • 使用 IDE 插件(如 Lombok 或 QueryDSL)可进一步减少手写 HQL 的出错概率

所有示例代码已托管至 GitHub:

👉 https://github.com/baeldung/tutorials/tree/master/persistence-modules/hibernate-enterprise


原始标题:Hibernate Error “Not all named parameters have been set” | Baeldung