当将 select for update nowait 与 jooq 一起使用时,语句不会引发异常,而是继续等待行解锁。
最近我尝试在 Spring Boot 中运行的 jooq 中使用 select for update nowait ,如下所示:
public void findByIdForUpdateNoWait(UUID id) {
dslContext.select()
.from(PAYMENT)
.where(PAYMENT.ID.eq(id))
.forUpdate()
.noWait()
.fetch();
}
并编写了一个测试来检查行为:
@Test
@Transactional(propagation = Propagation.REQUIRES_NEW)
void findByIdForUpdateNoWait_fail() {
UUID id = UUID.fromString("3d346f2f-9c44-4e8c-8479-f3eb4b46195f");
repository.findByIdForUpdateNoWait(id);
testTransactionProvider.runInSeparateTransaction(() -> {
assertThrows(DataAccessException.class,()->{
repository.findByIdForUpdateNoWait(id);
});
});
}
方法 runInSeparateTransaction 是:
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void runInSeparateTransaction(Runnable test) {
test.run();
}
测试方法卡住了。我在日志中看到 jooq 抛出错误 DataAccessException,但该错误未到达测试方法。 这是 jooq 生成的查询(基于日志)
select "payment"."id" where "payment"."id" = '3d346f2f-9c44-4e8c-8479-f3eb4b46195f' for update nowait
在测试运行时(当另一个事务锁定行时)使用此sql直接查询数据库时:
select * from payment ipi where ipi.id = '3d346f2f-9c44-4e8c-8479-f3eb4b46195f' for update nowait;
查询按照预期抛出锁定异常。
我应该如何创建 jOOQ 查询,以便它在行被锁定时抛出,就像本机查询一样,而不是等待它们解锁?
我正在使用 jOOQ 3.14.16 和 postgres 42.6.0
其实问题是我使用的
@Sql(scripts = "/sql/payment-tear-down.sql", config = @SqlConfig(transactionMode = ISOLATED), executionPhase = AFTER_TEST_METHOD)
实际上无法运行,因为事务仍然持有表上的锁,因此它挂起测试并且测试从未通过。