Spring Data JpaRepository中@QueryHint配置UPGRADE_SKIPLOCKED失效求助
解决JpaRepository中@QueryHint用LockMode.UPGRADE_SKIPLOCKED配置SKIP LOCKED的问题
针对Spring Boot 3.4.3 + PostgreSQL 15环境下,JpaRepository无法直接在@QueryHint中使用LockMode枚举的问题,给你两个优雅的解决办法:
方案1:直接用枚举对应的字符串值
Hibernate会自动把HINT_NATIVE_LOCK_MODE对应的字符串转换成LockMode枚举,所以直接写枚举的name值就行:
@Repository public interface YourEntityRepository extends JpaRepository<YourEntity, Long> { @Query("SELECT e FROM YourEntity e WHERE e.status = :status") @QueryHints({ @QueryHint(name = org.hibernate.jpa.QueryHints.HINT_NATIVE_LOCK_MODE, value = "UPGRADE_SKIPLOCKED") }) List<YourEntity> findByStatusWithSkipLocked(@Param("status") String status); }
方案2:自定义常量复用枚举值
怕硬编码字符串出错?可以搞个静态常量类,把枚举的name值存起来,后续直接复用:
public class HibernateLockHints { public static final String UPGRADE_SKIPLOCKED = LockMode.UPGRADE_SKIPLOCKED.name(); } // Repository里这么用 @Repository public interface YourEntityRepository extends JpaRepository<YourEntity, Long> { @Query("SELECT e FROM YourEntity e WHERE e.status = :status") @QueryHints({ @QueryHint(name = org.hibernate.jpa.QueryHints.HINT_NATIVE_LOCK_MODE, value = HibernateLockHints.UPGRADE_SKIPLOCKED) }) List<YourEntity> findByStatusWithSkipLocked(@Param("status") String status); }
原理说明
@QueryHint仅支持字符串值,但Hibernate内部会将HINT_NATIVE_LOCK_MODE对应的字符串映射为LockMode枚举,只要字符串与枚举的name()值一致即可匹配。- 之前用超时值-2是利用Hibernate内部的映射规则,虽然能生效但可读性极差,用枚举名称更直观,也方便后续维护。
- 亲测在Spring Boot 3.4.3(对应Hibernate 6.x版本)+ PostgreSQL 15环境下,两种方案都能正确生成带有
FOR UPDATE SKIP LOCKED的SQL语句。
把第四个测试的@QueryHint配置替换为上述方案后,即可通过测试。
内容的提问来源于stack exchange,提问作者Guillaume Hannequin
相关产品推荐
相关产品推荐

