【发布时间】:2020-10-20 04:36:41
【问题描述】:
我有以下场景:
@Service
public class ServiceA {
@Autowired private ServiceB serviceB;
public void runA(){
serviceB.runB()
}
}
@Service
public class ServiceB {
@Autowired private ServiceC serviceC;
@Transactional
public void runB(){
serviceC.runC()
...rest of the logic
}
}
@Service
public class ServiceC {
@Autowired private TestRepository testRepository;
@Transactional(propagation = Propagation.REQUIRES_NEW)
public boolean runC(){
Optional<TestEntity> testEntityOptional = testRepository.findByKeyAndType("Key", "Type");
if(testEntityOptional.isPresent()) {
testEntityOptional.get().setActive(true);
return true;
}
return false;
}
}
@Transactional
public interface TestRepository
extends JpaRepository<TestEntity, Integer>, JpaSpecificationExecutor<TestEntity> {
@Lock(LockModeType.PESSIMISTIC_WRITE)
@QueryHints({@QueryHint(name = "javax.persistence.lock.timeout", value = "5000")})
Optional<TestEntity> findByKeyAndType(@NotNull String key, @NotNull String type);
}
我期待下一个流程:
-
ServiceA.runA()调用ServiceB.runB() -
ServiceB.runB()打开 TRANSACTION_1(如果之前打开过,则使用事务),因为默认传播是REQUIRED -
ServiceB.runB()调用ServiceC.runC() -
ServiceC.runC()打开 TRANSACTION_2 因为传播是REQUIRED_NEW -
ServiceC.runC()调用TestRepository.findByKeyAndType()按某些条件获取 testEntity -
TestRepository.findByKeyAndType()从数据库返回符合条件的记录并将其锁定以供读取/更新 -
ServiceB.runC()处理记录 -
ServiceB.runC()返回值并提交 TRANSACTION_2 并释放锁 -
ServiceB.runB()返回并提交 TRANSACTION_1
但根据我的测试,情况并非如此。它接缝ServiceC.runC() 不创建新事务(TRANSACTION_2),即使设置了传播REQUIRED_NEW(或者它在返回时不提交它),并且仅当ServiceB.runB() 返回时才释放锁定(当提交TRANSACTION_1 时)
有人看到我在这里做错了吗?这是 SpringBoot 的正常行为吗?
锁定超时也不起作用: 我正在使用 Postgress v10 for DB,其中 lock_timeout 设置为“0”。
所以看起来@QueryHints({@QueryHint(name = "javax.persistence.lock.timeout", value = "5000")}) 不起作用,因为一旦记录被锁定,另一个尝试读取记录的事务会挂起一段时间,直到记录被解锁
【问题讨论】:
-
感谢您记录财产。我只是调试并 100% 确定没有打开新事务
标签: spring-boot hibernate jpa transactions spring-transactions