在批量更新命名查询的情况下,JPA 中不会更新版本

Posted

技术标签:

【中文标题】在批量更新命名查询的情况下,JPA 中不会更新版本【英文标题】:Version is not updated in JPA in case of bulk-update named queries 【发布时间】:2014-03-12 02:28:10 【问题描述】:

我正在使用 JPA 的 openjpa 2.1.0 实现。

我的实体中有带有@Version 注释的属性。

    /** version column to control concurrency*/  
    @Column(name = "XXX_VERSION")  
    @Version  
    private Integer xxxVersion;  

这里 XXX_VERSION 是表中的列,数据类型为数字,现在当我通过编辑实体调用合并时,openjpa 将从 XXX_VERSION 列的值增加 1。

public E update(E entity)   
        return entityManager.merge(entity);  
      

超出预期,工作正常。

但是当我使用命名查询来更新表中的某些列时,如下所示:

Query query = getEntityManager().createNamedQuery(update query passed here without version column in it);
 query.setParameter(PaymentConstants.QUERY_PARAM_XXX_ID, Long.valueOf(XXXId));
 query.executeUpdate();

然后版本不会增加,因为如果任何其他并发用户从他的会话中对数据库中的同一行执行任何操作,则版本不会在 XXX_VERSION 列中增加。

我试图将递增的版本传递给更新查询,它会抛出一个异常,说明查询语法无效。

如果使用命名查询进行更新查询,可以做些什么来增加版本?

【问题讨论】:

如果你使用 Hibernate 作为 JPA 提供者,那么对于 JPQL,Hibernate 可以强制增加版本。只需在“更新”关键字之后添加一个“版本化”关键字。更新版本的 BookingItemDO doName 设置 doName.isShipperLoad='Y' where doName.poNo='PO0001' 【参考方案1】:

恐怕这符合 JPA。以下是 JPA 规范(4.10 批量更新和删除操作)的摘录:

批量更新直接映射到数据库更新操作,绕过 乐观锁定检查。便携式应用程序必须手动更新 版本列的值(如果需要)和/或手动验证 版本列的值。

因此您必须手动执行此操作:获取条目并保存,每次一个。

【讨论】:

以上是关于在批量更新命名查询的情况下,JPA 中不会更新版本的主要内容,如果未能解决你的问题,请参考以下文章

JPA合并与持久化[重复]

JPA 的批量更新触发 TransactionalEventListener?

JPA的批量更新会触发TransactionalEventListener吗?

Java JPA,如何在没有销毁创建的情况下更新表?

JPA - 批量/批量更新 - 更好的方法是啥?

如何在 Controller 的 java spring JPA 中进行批量更新