Spring JPA + Hibernate + Postgres - 无法执行"FOR UPDATE OF"查询

3

我正在尝试在Postgres数据库上使用JPA和Hibernate实现悲观写锁定表,而不锁定相关表。

当前配置:

  • Java 17
  • Spring Boot 3.0.7
  • Hibernate 6.1.7.Final
  • Postgres 14.7

我没有使用显式的Hibernate方言声明。根据this - Hibernate应该自动配置方言。

我的当前JPA存储库代码:

@Lock(LockModeType.PESSIMISTIC_WRITE)
@QueryHints({
    @QueryHint(name = AvailableSettings.DEFAULT_BATCH_FETCH_SIZE, value = "" + Integer.MIN_VALUE),
    @QueryHint(name = AvailableSettings.USE_SECOND_LEVEL_CACHE, value = "false"),
    @QueryHint(name = AvailableSettings.JAKARTA_LOCK_TIMEOUT, value = "-2"),
    @QueryHint(name = "org.hibernate.lockMode.ps", value = "NONE")
})
@Query(value = """
    SELECT p
    FROM Payment p
        JOIN FETCH p.status ps
    WHERE ps.name IN :statuses
""")
Stream<Payment> getPaymentsStream(@Param("statuses") List<String> statuses);

我期望什么:
SELECT p1_0.*, --just skipped fields
    s1_0.id,
    s1_0.name
FROM
    payment p1_0
JOIN payment_status s1_0 ON
    s1_0.id = p1_0.status_id
    s1_0.name IN(?,?)
FOR UPDATE OF p1_0 SKIP LOCKED

我得到什么
SELECT p1_0.*, --just skipped fields
    s1_0.id,
    s1_0.name
FROM
    payment p1_0
JOIN payment_status s1_0 ON
    s1_0.id = p1_0.status_id
    s1_0.name IN(?,?)

select id from payment_status where id =? for update skip locked
select id from payment where id =? for update skip locked

我根据this的答案添加了org.hibernate.lockMode.ps提示,但没有任何变化。 此外,我已经使用nativeQuery = true进行了测试,一切正常。但是由于可能存在兼容性问题,我不想使用这种方法。
在Hibernate中有没有其他方法可以使FOR UPDATE OF起作用而不编写原生查询?
提前感谢您。 更新1 实体声明
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Entity
@DynamicUpdate
@DynamicInsert
@EqualsAndHashCode
@Table(name = "payment", schema = "xxx")
@ToString
public class Payment implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;
    
    /* column definitions */
    
    @ManyToOne
    @JoinColumn(name = "status_id", referencedColumnName = "id", nullable = true)
    private PaymentStatus status;
}

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Entity
@DynamicUpdate
@DynamicInsert
@EqualsAndHashCode
@Table(name = "payment_status", schema = "xxx")
@ToString
public class PaymentStatus implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @Column(name = "name")
    private String name;
}

你能提供实体的声明吗? - Semyon Kirekov
你能提供实体的声明吗? - Semyon Kirekov
@SemyonKirekov,我更新了我的问题,并添加了声明。 - ahgpoug
@SemyonKirekov,我在问题中更新了声明。 - ahgpoug
@SemyonKirekov,我在问题中更新了声明。 - undefined
1个回答

0

我对悲观的写锁定不太熟悉。我只知道悲观锁定(不包括"写"这个词)。这似乎是一个非常特殊的供应商特性。

我认为这是一个超过 SQL 语法和语义一部分的特殊供应商功能。我认为悲观的锁定是对缓存行为的深度干预,Hibernate 没有提供原生支持。


事实是 - 写锁定是有效的。但不是我期望的方式。 - ahgpoug
事实就是,写锁定确实起作用。但不是我期望的方式。 - ahgpoug
事实是 - 写锁定是有效的。但不是我期望的方式。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接