hibernate 如何使用悲观锁定实现跳过锁定功能?

yx2lnoni  于 2022-11-14  发布在  其他
关注(0)|答案(2)|浏览(157)

我想实现跳过锁。我正在使用Postgres 9.6.17。我正在使用以下代码

@Lock(LockModeType.PESSIMISTIC_WRITE)
@QueryHints({@QueryHint(name = "javax.persistence.lock.timeout", value = "-2")})
@Query("Select d from Demo d where d.id in (?1)")
List<Demo> getElementByIds(List<Long> ids);

我通过cmd(对进行数据库调用的两个服务的并行 curl 请求)同时从两个服务进行相同的数据库调用。我从一台服务器传递来自1的ID...4,从其他服务器传递来自1的ID...7。但是,如果第一个服务锁定了1...4行,然后第二个服务必须等到第一个服务移除其锁,但理想情况下,第二个服务应该返回我调用的第一个服务的第5...7行,如下所示

List<Long> ids = new ArrayList<>();
    ids.add(1l);
    ids.add(2l);
    ids.add(3l);
    ids.add(4l);
    List<Demo> demos = demoRepo.getElementByIds(ids);
    try{
        Thread.sleep(500);
    } catch (Exception e) {

    }
    logger.info("current time: " + System.currentTimeMillis());

在第二个服务中,我这样呼叫:

List<Long> ids = new ArrayList<>();
    ids.add(1l);
    ids.add(2l);
    ids.add(3l);
    ids.add(4l);
    ids.add(5l);
    ids.add(6l);
    ids.add(7l);
    try{
        Thread.sleep(100);
    } catch (Exception e) {

    }
    logger.info("current time: " + System.currentTimeMillis());
    List<Demo> demos = demoRepo.getElementByIds(ids);
    logger.info("current time: " + System.currentTimeMillis());

但这两个查询总是返回相同的行,这是我在等待另一个服务释放锁后询问的。
我正在使用的Spring JPA版本:

<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>2.2.5.RELEASE</version>

我还在应用程序级别本身尝试了spring.jpa.javax.sistence.lock.timeout=-2,这也不起作用。这两种方法似乎都像悲观写法一样有效。
请建议我如何实现跳过锁定功能。

lg40wkob

lg40wkob1#

这些问题似乎是正确的。
希望您使用的是支持Skip Lock功能的最新Postgres方言。
考虑到您正在使用的Postgres版本,应该使用以下方言。org.hibernate.Dialt.PostgreSQL95方言*
您可以参考this link了解更多信息

ecfsfe2w

ecfsfe2w2#

拉维·尚卡尔的回答是正确的。我测试过了,它真的起作用了。您需要指定方言版本。例如,在春靴中

spring.jpa.database-platform=org.hibernate.dialect.PostgreSQL94Dialect

此外,如果您使用字符串的常量,代码将更具可读性。

@QueryHint(name = AvailableSettings.JPA_LOCK_TIMEOUT, value = LockOptions.SKIP_LOCKED.toString())

相关问题