4.2. 关于 HQL 语句


HQL 和 Java 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]
Copy to Clipboard Toggle word wrap

UPDATE

HQL 中的 UPDATE 语句与 Java 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
Copy to Clipboard Toggle word wrap

删除

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

delete_statement ::= delete_clause [where_clause]

delete_clause ::= DELETE FROM entity_name [[AS] identification_variable]
Copy to Clipboard Toggle word wrap

INSERT

HQL 中的 INSERT 语句的 BNF 是:

insert_statement ::= insert_clause select_statement

insert_clause ::= INSERT INTO entity_name (attribute_list)

attribute_list ::= state_field[, state_field ]*
Copy to Clipboard Toggle word wrap

没有与它对应的 Java 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();
Copy to Clipboard Toggle word wrap

示例:批量删除语句

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();
Copy to Clipboard Toggle word wrap

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

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

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

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

重要

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

关于 INSERT 语句

HQL 添加了定义 INSERT 语句的功能。没有与它对应的 Java 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 ]*
Copy to Clipboard Toggle word wrap

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();
Copy to Clipboard Toggle word wrap

示例: 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();
Copy to Clipboard Toggle word wrap

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

返回顶部
Red Hat logoGithubredditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

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

让开源更具包容性

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

關於紅帽

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

Theme

© 2025 Red Hat