java 使用JPA同步并发批处理更新

qyzbxkaa  于 2023-02-02  发布在  Java
关注(0)|答案(1)|浏览(164)

这个例子经过了修改和简化,但类似于我试图修复的遗留代码中的一个实际问题。
我有一个MSSQL CAR表(其中id是主键)
| 身份证|制造|地位|
| - ------|- ------|- ------|
| 1个|宝马|清洗|
| 第二章|宝马|肮脏|
| 三个|宝马|肮脏|
| 四个|福特|肮脏|
| ...|...|...|
/washNextCars端点。

@PatchMapping("/washNextCars")
public ResponseEntity<List<Car>> washNextCars(
      @RequestBody WashCarBody body,
      @RequestParam String status,
      @RequestParam String make,
      @RequestParam Integer limit) {
  ...
}

以下请求将下一个10车厢的状态从DIRTY更改为WASHED

PATCH /washNextCars?status=DIRTY&make=BMW&limit=10
{
    "status": "WASHED"
}

这是大致的业务逻辑:

@Transactional
  public List<Car> washNextCars(WashCarDTO dto) {

    // SELECT TOP ? * FROM CAR WHERE make=? AND status='DIRTY' ORDER BY id ASC 
    List<Car> nextCars = carRepository.findNextCars(limit, make, status);

    // do some complex validation on every car if it can be washed, therefore can't do everything in one single UPDATE query

    cars.forEach(car -> {
      car.setStatus("WASHED");
    });
    carRepository.saveAll(nextCars);
  }

这个端点在顺序调用时工作正常,但在并行调用时,它会尝试同时对同一组汽车执行更新,而不是对下一批汽车执行更新。

    • 问题:**
  • 在第一个呼叫完成之前,如何同步呼叫?
  • 请注意,这必须在数据库级别实现,因为API部署为多个副本
  • 我找到了以下选项:
  • @Transactional(isolation = READ_UNCOMMITED)
  • 这需要在执行业务逻辑中的任何其他语句之前将cars更新为WASHED,对吗?
  • @Lock(PESSIMISTIC_WRITE_LOCK)-未提供预期效果
  • 实现这一目标的正确途径是什么?
r55awzrz

r55awzrz1#

尝试使用UPDLOCK:

SELECT ... FROM tab1 WITH (UPDLOCK) WHERE ...

类似于
选择更新
在甲骨文。

相关问题