如何执行以 List 作为参数值的 JPA 批量更新语句

How to execute a JPA Bulk Update statement which takes a List as a parameter value

我有一个如下所示的更新查询

UPDATE 
    table_name 
SET 
    column_name = ? 
WHERE
    column_name = ? AND id in (?)

所以 JPA 事务是

em.createNativeQuery(Update_QUERY)
   .setParameter(1, updatedStatus)
   .setParameter(2, currentStatus)
   .setParameter(3, ids)
   .executeUpdate();

该方法的输入是 List id、currentStatus 和 updatedStatus

如何将列表作为单个参数传递,如果我将列表转换为逗号分隔的字符串,我会收到错误指定的文本不是数字,因为 In 子句中不允许使用字符串。

How do I pass the List as a single parameter

示例方法:

String jpql = "UPDATE NameEntity ne " + 
              "SET ne.valstring = :updated_status " +
              "WHERE ne.valstring = :current_status AND ne.id IN :ids";
em.createQuery(jqpl)
  .setParameter("updated_status", updatedStatus)
  .setParameter("current_status", currentstatus)
  .setParameter("ids", Arrays.asList(ids))
  .executeUpdate();

三个简单的规则:

  1. 使用本机 SQL 在 table 上 映射到实体的批量更新/删除。

    本机 SQL 查询直接在数据库 table 上工作,绕过持久性上下文(一组托管实体),因此如果给定数据库 table没有对应实体

  2. 使用 JPQL 批量更新/删除 table 映射到实体

    如果给定的数据库 table 被实体映射,使用 SQL 更新/删除将导致持久性上下文和底层数据库之间的不一致,因此请改用 JQPL 对应项,并且持久性提供程序将负责一致性。

  3. 批量更新/删除应该作为事务中的第一个操作执行,或者最好在它自己的事务中执行。

设置列表参数

接受 Object 参数的 JPA Query interface setParameter 方法:

Query setParameter(String name, Object value)

可以取一个List作为参数值。

这对 JPQL、条件 API 或批量更新和删除查询的工作方式相同:

List<Post> posts = entityManager.createNativeQuery("""
    UPDATE 
        post
    SET 
        status = :newStatus
    WHERE 
        status = :oldStatus AND
        id IN :ids

    """, Post.class)
.setParameter("oldStatus", PostStatus.PENDING)
.setParameter("newStatus", PostStatus.APPROVED)
.setParameter("ids", List.of(1L, 2L, 3L))
.executeUpdate();

For more details about executing bulk update and delete statements with JPA and Hibernate, check out this article as well.