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

Spring Boot 3升级后@Lock注解引发继承实体SQL语法异常

解决Spring Boot 3.2.3(Hibernate 6)中TABLE_PER_CLASS继承下OPTIMISTIC_FORCE_INCREMENT锁的SQL语法错误

问题重现

  • 环境变化:从Spring Boot 2.7.x升级至3.2.3(对应Hibernate 6)后出现异常,旧版本无此问题
  • 实体结构:抽象父实体Animal配置了@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)和@Version乐观锁注解,子类为Dog
  • 触发场景:在AnimalRepository的findAll方法上添加@Lock(LockModeType.OPTIMISTIC_FORCE_INCREMENT)注解,查询Dog数据并更新保存时抛出SQLGrammarException
  • 错误详情:Hibernate生成了更新不存在的animal表的SQL语句(update animal set version=? where id=? and version=?),而非实际存在的Dog表;移除@Lock注解后操作恢复正常。

原因分析

Hibernate 6对TABLE_PER_CLASS继承策略下的乐观锁强制递增逻辑做了调整,当在父类Repository方法上使用OPTIMISTIC_FORCE_INCREMENT锁时,框架未能正确识别该继承模式下需要操作子类对应的物理表,错误地生成了针对父类表的更新语句。

解决方案

1. 移锁至子类Repository

将@Lock(LockModeType.OPTIMISTIC_FORCE_INCREMENT)注解从父类AnimalRepository的方法上,转移到子类DogRepository的对应方法上,让Hibernate明确操作目标表:

// 正确写法:子类Repository加锁
public interface DogRepository extends JpaRepository<Dog, Long> {
    @Lock(LockModeType.OPTIMISTIC_FORCE_INCREMENT)
    List<Dog> findAll();
}

2. 更换继承策略(业务允许的情况下)

如果业务逻辑不依赖TABLE_PER_CLASS,可以考虑替换为JOINED或SINGLE_TABLE继承策略,这两种模式在Hibernate 6中对乐观锁的支持更稳定:

@Entity
@Inheritance(strategy = InheritanceType.JOINED) // 或InheritanceType.SINGLE_TABLE
public abstract class Animal {
    @Id
    @GeneratedValue
    private Long id;
    
    @Version
    private Integer version;
    
    // 其他字段和方法
}

3. 手动维护版本号递增

移除@Lock注解,在更新实体时手动递增version字段,确保乐观锁语义生效:

// Service层示例
@Transactional
public void updateDog(Long dogId) {
    Dog dog = dogRepository.findById(dogId).orElseThrow();
    // 手动递增版本号
    dog.setVersion(dog.getVersion() + 1);
    // 执行更新操作
    dogRepository.save(dog);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 12:24:57