Hibernate.org社区文档

第 7 章 批处理

7.1. 批量更新/删除

在完全的对象/关系映射中,批量处理通常很难。ORM 都是关于对象状态管理的,这意味着对象状态在内存中可用。然而,Hibernate 有些用于优化批量处理的功能,这些功能在 Hibernate 参考指南中进行介绍,然而,EJB3 持续性略有不同。

如已讨论的那样,自动而透明的对象/关系映射与对象状态管理有关。这意味着对象状态在内存中可用,因此直接在数据库中更新或删除(使用 SQL UPDATEDELETE)数据不会影响内存中的状态。但是,Hibernate 提供了通过 JP-QL 执行批量 SQL 风格 UPDATEDELETE 语句的方法(第 8 章,JP-QL:对象查询语言)。

UPDATEDELETE 语句的伪语法为:( UPDATE | DELETE ) FROM? ClassName (WHERE WHERE_CONDITIONS)?。请注意

  • 在 from 子句中,FROM 关键字是可选的。

  • 在 from 子句中只能指定一个类名,并且不能有别名(这是 Hibernate 当前的限制,并将很快消除)。

  • 在批量 JP-QL 查询中不能指定任何连接(隐式或显式)。可以在 where 子句中使用子查询。

  • where 子句也是可选的。

例如,要执行 JP-QL UPDATE,请使用 Query.executeUpdate() 方法

EntityManager entityManager = entityManagerFactory.createEntityManager();

entityManager.getTransaction().begin();
String jpqlUpdate = "update Customer set name = :newName where name = :oldName"
int updatedEntities = entityManager.createQuery( jpqlUpdate )
                            .setParameter( "newName", newName )
                            .setParameter( "oldName", oldName )
                            .executeUpdate();
entityManager.getTransaction().commit();
entityManager.close();

要执行 JP-QL DELETE,请使用相同的 Query.executeUpdate() 方法(该方法的名称面向那些熟悉 JDBC 的 PreparedStatement.executeUpdate() 的人)

EntityManager entityManager = entityManagerFactory.createEntityManager();

entityManager.getTransaction().begin();
String hqlDelete = "delete Customer where name = :oldName";
int deletedEntities = entityManager.createQuery( hqlDelete )
                            .setParameter( "oldName", oldName )
                            .executeUpdate();
entityManager.getTransaction().commit();
entityManager.close();

Query.executeUpdate() 方法返回的 int 值指示受操作影响的实体数。这可能与数据库中受影响的行数相关,也可能不相关。例如,对于联接子类,JP-QL 批量操作可能导致执行多个实际 SQL 语句。返回的数字指示受该语句影响的实际实体数。回到联接子类的示例中,针对一个子类的删除实际可能导致不仅删除映射到该子类的表,还删除“根”表和继承层次结构中更下方的联接子类表。