4.2. 关于 HQL 语句


HQL 和 Jakarta Persistence 查询语言都允许 SELECTUPDATE 和 DELETE 语句。HQL 还允许 INSERT 语句,其格式类似于 SQL INSERT-SELECT

下表显示了各种 HQL 语句的 Backus-Naur Form(BNF)表示法中的语法。

Expand
表 4.1. HQL 语句
声明描述

SELECT

HQL 中用于 SELECT 语句的 BNF 是:

select_statement :: =
        [select_clause]
        from_clause
        [where_clause]
        [groupby_clause]
        [having_clause]
        [orderby_clause]

UPDATE

HQL 中的 UPDATE 语句与 Jakarta Persistence 查询语言相同。

update_statement ::= update_clause [where_clause]

update_clause ::= UPDATE entity_name [[AS] identification_variable]
        SET update_item {, update_item}*

update_item ::= [identification_variable.]{state_field | single_valued_object_field}
        = new_value

new_value ::= scalar_expression |
                simple_entity_expression |
                NULL

删除

HQL 中的 DELETE 语句的 BNF 与 Jakarta Persistence 查询语言相同。

delete_statement ::= delete_clause [where_clause]

delete_clause ::= DELETE FROM entity_name [[AS] identification_variable]

INSERT

HQL 中的 INSERT 语句的 BNF 是:

insert_statement ::= insert_clause select_statement

insert_clause ::= INSERT INTO entity_name (attribute_list)

attribute_list ::= state_field[, state_field ]*

没有与这一点相当的 Jakarta Persistence 查询语言。

警告

Hibernate 允许使用数据操作语言(DML)直接通过 Hibernate 查询语言(HQL)批量插入、更新和删除数据。

使用 DML 可能会违反对象/关系映射,并可能会影响对象状态。对象状态保留在内存中,使用 DML 时,内存中对象的状态不受影响,具体取决于对底层数据库执行的操作。如果使用 DML,则必须小心使用内存中数据。

关于 UPDATE 和 DELETE 语句

UPDATE 和 DELETE 语句的伪syntax 是:

(更新 | 从中删除 )EntityName(WHERE where_conditions)?

注意

FROM 关键字和 WHERE 术语是可选的。FROM 子句负责定义可供查询的其余部分使用的对象模型类型的范围。它还负责定义其余查询可用的所有标识变量。WHERE 子句允许您优化返回的实例列表。

执行 UPDATEDELETE 语句的结果是实际受影响的行数(更新或删除)。

示例:批量更新语句

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();

String hqlUpdate = "update Company set name = :newName where name = :oldName";
int updatedEntities = s.createQuery( hqlUpdate )
        .setString( "newName", newName )
        .setString( "oldName", oldName )
        .executeUpdate();
tx.commit();
session.close();

示例:批量删除语句

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();

String hqlDelete = "delete Company where name = :oldName";
int deletedEntities = s.createQuery( hqlDelete )
        .setString( "oldName", oldName )
        .executeUpdate();
tx.commit();
session.close();

Query.executeUpdate() 方法返回的 int 值指示受操作影响的数据库内实体数量。

在内部,数据库可能会使用多个 SQL 语句来执行响应 DML 更新 或删除 请求 的操作。这可能是因为表和需要更新或删除的连接表之间存在关系。

例如,如上例所示,发出删除声明可能实际上不仅对使用 oldName 命名的 公司的 Company 表执行删除,而且会对合并表执行删除。因此 由于 成功执行了上例,与 Employee 表的双向多对多关系也会从相应的加入表中丢弃行。

已删除的Entries 值包含操作影响的所有行的计数,包括 join 表中的行。

重要

执行批量更新或删除操作时应小心,因为它们可能会导致数据库和活动持久化上下文中的实体不一致。通常,批量更新和删除操作应只在新持久性上下文中的事务内执行,或者在获取或访问状态可能受到此类操作影响的实体之前执行。

关于 INSERT 语句

HQL 添加了定义 INSERT 语句的功能。没有与这一点相当的 Jakarta Persistence 查询语言。HQL INSERT 语句的 Backus-Naur Form(BNF)是:

insert_statement ::= insert_clause select_statement

insert_clause ::= INSERT INTO entity_name (attribute_list)

attribute_list ::= state_field[, state_field ]*

attribute_list 与 SQL INSERT 语句中的列规格类似。对于涉及映射继承的实体,在 properties _list 中只能使用直接在指定实体上定义的属性。不允许超级类属性,子类属性并不合理。换句话说,INSERT 语句本质上是非私有的。

警告

select_statement 可以是任何有效的 HQL 选择查询,注意返回类型必须与插入预期的类型匹配。目前,这会在查询编译过程中检查,而不是让检查与数据库相连接。这可能会导致 Hibernate 类型与 相等 的问题 例如,这可能会导致映射为 org.hibernate.type.DateType 的属性和定义为 org.hibernate.type.TimestampType 的属性之间不匹配问题,即使数据库可能无法区分或处理转换。

对于 id 属性,插入语句为您提供两个选项:您可以在 attribute_list 中明确指定 id 属性,在这种情况下,从对应的 select 表达式获取它的值,或者从 attribute_list 中省略它,在这种情况下使用生成的值。只有使用"在数据库中操作"的 id 生成器时才可使用后一种选项;尝试将此选项用于任何"内存中"类型生成器将导致解析过程中出现异常情况。

对于不确定的锁定属性,插入语句再次为您提供两个选项:您可以在 attribute_list 中指定 属性,在这种情况下,它的值取自对应的选择表达式,或者从 attribute_list 中省略它,在这种情况下,使用了对应的 org.hibernate.type.VersionType 定义的 seed 值

示例:INSERT 查询语句

String hqlInsert = "insert into DelinquentAccount (id, name) select c.id, c.name from Customer c where ...";
int createdEntities = s.createQuery(hqlInsert).executeUpdate();

示例: Bulkert Statement

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();

String hqlInsert = "insert into Account (id, name) select c.id, c.name from Customer c where ...";
int createdEntities = s.createQuery( hqlInsert )
        .executeUpdate();
tx.commit();
session.close();

如果不使用 SELECT 语句提供 id 属性的值,则会为您生成标识符,只要底层数据库支持自动生成的密钥。此批量插入操作的返回值是数据库中实际创建的条目数。

Red Hat logoGithubredditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。 了解我们当前的更新.

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

Theme

© 2026 Red Hat
返回顶部