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
相关产品推荐
相关产品推荐

