JPA使用@Version时如何实现软删除?版本字段同步问题求解
带@Version的JPA实体实现软删除的正确方案
问题根源
你猜的没错,报错核心原因是:Hibernate处理乐观锁(@Version)时会校验操作的版本一致性,但最初的@SQLDelete语句既没把version作为更新条件,也没更新version字段,导致乐观锁验证失败,抛出数据完整性异常。
你后来修改的@SQLDelete虽然加了version条件,但没更新version值,会导致依赖版本号的其他操作无法感知这次软删除的变更,进而引发并发问题。
正确实现方式
1. 修改实体类的注解与字段映射
需要同时完成三件事:
- 在
@SQLDelete中更新version字段(自增1),并保留version作为where条件 - 添加
@Where注解,让所有默认查询自动过滤已软删除的记录 - 确保
isDeleted字段的映射正确
修改后的实体类代码:
@Entity @Data @AllArgsConstructor @NoArgsConstructor // 软删除时更新is_deleted和version,同时用student_id和version做乐观锁校验 @SQLDelete(sql = "update student set is_deleted=true, version=version+1 where student_id=? and version=?") // 默认查询排除已软删除的记录 @Where(clause = "is_deleted = false") public class Student { @Id @GeneratedValue(generator = "uuid2") @GenericGenerator(name = "uuid2", strategy = "org.hibernate.id.UUIDGenerator") private String studentId; @Column(nullable = false, columnDefinition = "VARCHAR(255)") private String name; @Column(name = "age") private Integer age; @Version private Integer version; private boolean isDeleted; }
2. 服务层代码无需修改
你现有的deleteSt方法保持不变即可:
@Transactional public String deleteSt(String id) { sr.deleteById(id); return "Deleted"; }
为什么这么做?
- 更新version字段:软删除本质是一次更新操作,必须更新
version值,这样其他依赖version做乐观锁的操作能感知到这条数据已被修改,避免并发冲突 - where条件带version:确保只有当前版本的数据会被软删除,符合乐观锁的校验逻辑,防止并发情况下的误操作
- @Where注解:让JPA的默认查询(比如
findById、findAll)自动排除已软删除的记录,不需要在每个查询里手动加过滤条件
内容的提问来源于stack exchange,提问作者Vaibhav
相关产品推荐
相关产品推荐

