事务如何真正工作 - 简单用例(sping boot)?

我试图了解我是否在做正确的交易。我在 Spring Boot 上使用 PostgreSQL 构建了一个小型 REST API。


案例是“保留” - 传入请求应该找到某个实体并将其状态设置为“保留”。必须防止的是两个请求返回同一个实体。


目前我将整个端点处理程序包装在一个事务中(如下)。据我了解,系统基本上会对当前状态进行快照,然后第一个请求将修改表。


问题是,当第二个请求进来时,在第一个仍然在事务内时,会发生什么?我需要 find() 查询将等到第一个事务结束然后继续。至少在理论上,它会像这样工作吗?


@Transactional

@RequestMapping(value = "/newTour", method = RequestMethod.GET, headers = "Accept=application/xml",

        consumes = "application/xml", produces = "application/xml")

public @ResponseBody ResponseEntity<?> addTourReservation(@RequestBody PartialTourUpdate partialUpdate) {



    try{ 

            List<Tour> tours = tourRepo.findFirstPessimisticByTourTypeInAndStatusOrderByPriorityDesc(partialUpdate.getTourType(), Tour.STATUS_OPEN);

            if (tours != null && tours.size() > 0) {

                Tour tour = tours.get(0);

                tour.setReservationID(partialUpdate.getReservationID());

                tour.setStatus(Tour.STATUS_TO_RESERVE);

                tourRepo.save(tour);

                orderRepo.updateReservationStatus(true, tour.getTourID()); 

                return new ResponseEntity<Tour>(tour, HttpStatus.CREATED);

            } else {

                rM.setValue(ResultMessage.ErrorCode.LOS_NOT_FOUND);

                rM.log();

                return new ResponseEntity<ResultMessage>(rM, HttpStatus.OK);

            }



    } catch (Exception e) 

    {

        rM.setValue(ResultMessage.ErrorCode.LOS_UNKNOWN);

        rM.log();

        return new ResponseEntity<ResultMessage>(rM, HttpStatus.OK);

    }


慕仙森
浏览 132回答 2
2回答

月关宝盒

锁定一行以防止并发事务读取它意味着排他锁。使用 JPA,这是使用PESSIMISTIC_WRITE锁实现的您需要使用&nbsp;@Lock(LockModeType.PESSIMISTIC_WRITE)请注意,这将跨越整个tour表的锁,防止任何并发事务读取任何行,这可能意味着重负载下的线程争用问题。另一种方法是选择所有可用的游览,并在列表中保留一个随机选择的游览,如果更新触发异常,则使用entityManager.lock(tour, LockModeType.PESSIMISTIC_FORCE_INCREMENT)(实体必须具有@Version属性)预先锁定它(并且仅锁定它,而不是整个表)(如果另一笔交易已经保留了它)只需选择另一个并尝试更新它。但是,最好的方法仍然是让数据库处理并发问题并使用单个 SQL(或 HQL)更新查询保留“游览”(您的方法中没有业务逻辑,因此您无需检索和操作更新之前的实体)。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java