【发布时间】:2016-01-16 22:16:43
【问题描述】:
我有一种方法的服务:
@Service
public class DefaultTestService implements TestService {
private static final Logger LOGGER = Logger.getLogger(DefaultTestService.class);
@Autowired
private TestRepository testRepository;
@Transactional(readOnly = false, isolation = Isolation.SERIALIZABLE)
@Override
public void incrementAndGet(Long testModelId) {
LOGGER.debug("Transaction is active: " + TransactionSynchronizationManager.isActualTransactionActive());
final TestModel tm = testRepository.findOne(testModelId);
if (tm != null) {
LOGGER.debug("Updated " + testModelId + " from value: " + tm.getValue());
tm.setValue(tm.getValue() + 1);
testRepository.save(tm);
} else {
LOGGER.debug("Saved with id: " + testModelId);
final TestModel ntm = new TestModel();
ntm.setId(testModelId);
testRepository.save(ntm);
}
}
}
我正在运行带有 testModelId = 1L 参数的 2 个并行调用配置的 Gatling。
由于这些调用,我收到了错误:
org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "test_model_pkey"
从日志中我可以看到,有两个调用同时进入了这个方法,并且每个都打印了日志
"Saved with id: 1"
"Saved with id: 1"
我假设在此方法上添加事务注释会阻止 testRepository.findOne(testModelId) 行上的一个调用,直到其他调用完成其执行,但正如我从日志中看到的那样,它以不同的方式工作。
所以我的问题是,在这种情况下,当并发访问出现时,事务是如何工作的?以及如何处理这种并发访问的情况?
【问题讨论】:
标签: java spring spring-data spring-transactions