You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用JPA/Crud Repository与@Version注解时的版本更新问题

解决Hibernate @Version更新后本地对象版本号未同步的问题

问题描述

在MySQL中使用@Version注解实现乐观锁,执行两次连续更新时抛出org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction错误。原因是第一次更新后数据库版本号已递增,但本地实体对象仍保留旧版本号,导致第二次更新时乐观锁校验失败。调试发现save()/saveAll()方法没有返回更新后的版本号。

实体类核心代码:

@Entity
@Table(name = "CO_PAR_ACTIVATION_DIFFUSION_ENTITE")
public class ActivationDiffusionEntiteDb extends AbstractDatabaseObject {

    private static final long serialVersionUID = -6355794857690807029L;
    @Id
    @SequenceGenerator(name = "TCO_ACTENT_GENERATOR", allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.AUTO, generator = "TCO_ACTENT_GENERATOR")
    private Long id;

    // 其他字段省略

    @Version
    private Long version;
}

无需重新查询的解决方案

1. 使用merge()替代save()/saveAll()

merge()方法会处理分离状态的实体,执行数据库更新后,返回一个处于托管状态的实体实例,该实例包含最新的版本号。直接使用返回的对象进行后续操作即可:

// 假设yourEntity是分离状态的实例
ActivationDiffusionEntiteDb updatedEntity = entityManager.merge(yourEntity);
// 此时updatedEntity.getVersion()就是更新后的版本号,可用于后续更新

2. 确保操作在同一持久化上下文(Session)内

如果两次更新操作处于同一个Hibernate Session(或Spring的@Transactional方法内),Hibernate会在第一次更新完成后(事务提交或flush时)自动同步本地实体的版本号。示例:

@Transactional
public void updateTwice(ActivationDiffusionEntiteDb entity) {
    // 第一次更新,Hibernate自动标记实体为脏数据
    entityManager.save(entity);
    // 此时Hibernate尚未执行数据库操作,若要立即同步可调用flush
    entityManager.flush();
    // 本地实体的version已更新,可直接执行第二次更新
    entity.setSomeField("newValue");
    entityManager.save(entity);
}

3. 调用flush()强制同步上下文

如果坚持使用save(),可以在第一次save()后调用entityManager.flush(),强制Hibernate立即执行数据库更新操作,并将最新的版本号同步回本地实体:

entityManager.save(yourEntity);
entityManager.flush(); // 强制同步数据库状态到本地实体
// 此时yourEntity.getVersion()已更新为最新值,可进行第二次更新

原理说明

save()方法对于托管状态的实体,仅会将其标记为"脏数据",实际的数据库更新和版本号递增操作会延迟到事务提交或flush()时执行。如果在这之前尝试第二次更新,本地实体的版本号还是旧值,导致乐观锁校验失败。而merge()会直接处理实体的更新逻辑,并返回同步后的实例;同一Session内的操作则会由Hibernate自动维护实体状态的一致性。

内容的提问来源于stack exchange,提问作者CJunior

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 03:07:40