【发布时间】:2019-01-25 11:05:11
【问题描述】:
我们有一个如下所示的控制器:
@RestController()
public class TestController {
@Autowired
TestService testService;
....
// Update request
@PutMapping("/update")
public ResponseEntity<Sample> updateApi(@PathVariable(value = "id") Long id,
@Valid @RequestBody Sample sampleDetails) {
return new ResponseEntity<Sample>(testService.updateSample(id, sampleDetails), HttpStatus.OK);
}
....
服务类(依赖于 JPA 存储库)如下所示:
@Service
public class TestService {
@Autowired
TestRepository testRepository;
// update sample
public Api updateSample(long sampleId, Sample details) {
// Get object to be updated
Sample sample = apiRepository.findById(sampleId);
// Update required fields
sample.setName(details.getName());
sample.setBody(details.getBody());
return apiRepository.save(api);
}
- 在上述服务(TestService)中,setName 和 setBody 方法调用 jpa 存储库:这些步骤是否保持状态(即非无状态),并且在处理并发请求时可能会导致问题。或者我们是否需要将此服务(或服务中的 updateSample 方法)的范围设置为“web-aware Spring ApplicationContext”
- 与第 1 点类似,此行:“Sample sample = apiRepository.findById(sampleId);”,此行是线程安全的还是会在处理并发请求时导致问题。
【问题讨论】:
-
需要考虑两件事:1) 数据库隔离级别,锁定 2)
@Transactional- 如果您的方法上没有该注释,那么这些调用将在不同的事务中。 -
这段代码是完全线程安全的。只要你不在类级别保持状态就没有问题,
-
不要在类级别保持状态 => 这是否意味着在方法内部创建的变量是线程安全的?并且只有单个线程将在给定时间点执行该方法?
-
你的 bean 是原型还是单例?我认为该方法不是“线程安全的”。线程 A 和线程 B 修改同一个 sampleId 对象,数据库中的结果可能不是你想要的。
-
它只是一个单例
标签: java spring spring-boot