4.2. 关于 HQL 语句
HQL 和 Java Persistence 查询语言都允许 SELECT
、UPDATE 和
DELETE
语句。HQL 还允许 INSERT
语句,其格式类似于 SQL INSERT-SELECT
。
下表显示了各种 HQL 语句的 Backus-Naur Form(BNF)表示法中的语法。
声明 | 描述 |
---|---|
|
HQL 中用于 |
|
HQL |
|
HQL 中的 delete_statement ::= delete_clause [where_clause] delete_clause ::= DELETE FROM entity_name [[AS] identification_variable]
|
|
HQL 中的 insert_statement ::= insert_clause select_statement insert_clause ::= INSERT INTO entity_name (attribute_list) attribute_list ::= state_field[, state_field ]*
没有与它对应的 Java Persistence 查询语言。 |
Hibernate 允许使用数据操作语言(DML)直接通过 Hibernate 查询语言(HQL)批量插入、更新和删除数据。
使用 DML 可能会违反对象/关系映射,并可能会影响对象状态。对象状态保留在内存中,使用 DML 时,内存中对象的状态不受影响,具体取决于对底层数据库执行的操作。如果使用 DML,则必须小心使用内存中数据。
关于 UPDATE 和 DELETE 语句
UPDATE 和
DELETE
语句的伪syntax 是:
(更新 | 从中删除 )EntityName(WHERE where_conditions)?
。
FROM
关键字和 WHERE
术语是可选的。FROM
子句负责定义可供查询的其余部分使用的对象模型类型的范围。它还负责定义其余查询可用的所有标识变量。WHERE
子句允许您优化返回的实例列表。
执行 UPDATE
或 DELETE
语句的结果是实际受影响的行数(更新或删除)。
示例:批量更新语句
示例:批量删除语句
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 ]*
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();
String hqlInsert = "insert into DelinquentAccount (id, name) select c.id, c.name from Customer c where ...";
int createdEntities = s.createQuery(hqlInsert).executeUpdate();
示例: Bulkert Statement
如果不使用 SELECT
语句提供 id
属性的值,则会为您生成标识符,只要底层数据库支持自动生成的密钥。此批量插入操作的返回值是数据库中实际创建的条目数。