乐观锁解决库存超卖问题

public BaseResult creatOneOrder(FlightOrderServiceImpl orderService, List> passengers,Map selectFlightMap,String account) throws Exception {
            //如果是单程
            //判断座位数是否>=1
            //是的话就直接减库存
            //不是就return 201,库存不够

            int k=0;

            FlightSeat seat = seatService.getById(selectFlightMap.get("seatId"));
            if(seat.getRestNum()<1){
                return new BaseResult(201,"库存不够了");
            }

            seat.setRestNum(seat.getRestNum()-1);
            boolean updateResult = seatService.updateById(seat);
            if(!updateResult){
                //如果更新失败
                //说明在更新前有其他人已经对该行剩余量进行了修改
                //就再试一次,先判断库存
                int maxRetries = 5; //最大重试次数
                int retryCount = 0;

                while (retryCount < maxRetries) {
                    // 获取最新的座位信息
                    FlightSeat updatedSeat = seatService.getById(selectFlightMap.get("seatId"));

                    // 检查座位是否仍然可用
                    if (updatedSeat.getRestNum() < 1) {
                        return new BaseResult(201, "库存不够了");
                    }

                    // 尝试更新座位信息
                    updatedSeat.setRestNum(updatedSeat.getRestNum() - 1);
                    boolean retryUpdateResult = seatService.updateById(updatedSeat);

                    // 检查更新操作的结果
                    if (retryUpdateResult) {
                        // 成功更新,生成订单,跳出循环
                        k=1;
                        break;

                    } else {
                        // 增加重试计数并进行下一次尝试
                        retryCount++;
                    }

                    if (retryCount == maxRetries) {
                        return new BaseResult(202, "更新失败,重试次数已达上限");
                    }
                }


            }
            else {
                k =1;
            }

            if(k==1){//k=1说明库存成功减少了

                FlightOrder Order = new FlightOrder();
                // 获取当前时间
                LocalDateTime currentTime = LocalDateTime.now();

                // 如果你想以特定格式输出当前时间,可以使用 DateTimeFormatter
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                String formattedCurrentTime = currentTime.format(formatter);
                Order.setDate(formattedCurrentTime);

                // 设置超时时间为当前时间的15分钟后
                LocalDateTime timeoutTime = currentTime.plusMinutes(15);
                String formattedTimeoutTime = timeoutTime.format(formatter);
                Order.setTimeout(formattedTimeoutTime);


                Order.setOrderId(String.valueOf(new SnowUtil(0,0).getId()));


//                redisTemplate.opsForValue().set(Order.getOrderId(), Order.getOrderId(), 15, TimeUnit.MINUTES);
                redisTemplate.opsForValue().set(Order.getOrderId(), Order.getOrderId(), 15, TimeUnit.MINUTES);

                Flight flight = new Flight();
                flight = flightService.getById(selectFlightMap.get("flightId"));

                Order.setFlightCode(flight.getFlightCode());
                Order.setStage("待支付");
                Order.setWay("单程");
                Order.setUserId(account);


                Air air = airService.getById(flight.getAirId());
                Order.setPrice(seat.getPrice());
                Order.setAllPrice(seat.getPrice());
                Order.setSeatType(seat.getSeatType());
                Order.setDepCity(flight.getDepCity());
                Order.setDepDate(flight.getDepDate());
                Order.setDepTime(flight.getDepTime());
                Order.setArrCity(flight.getArrCity());
                Order.setArrDate(flight.getArrDate());
                Order.setArrTime(flight.getArrTime());
                Order.setDepAirport(flight.getDepAirport());
                Order.setArrAirport(flight.getArrAirport());
                Order.setAirlineName(flight.getAirlineName());
                Order.setAirType(air.getType());


                orderService.save(Order);


                for (Map pas : passengers) {
                    FlightPassenger passenger = new FlightPassenger();
                    passenger.setOrderId(Order.getOrderId());
                    passenger.setName(pas.get("name"));
                    passenger.setIdentityId(pas.get("sfz"));
                    passenger.setPhone(pas.get("phone"));
                    passengerService.save(passenger);
                }
                return new BaseResult(200,"支付成功",Order.getOrderId());
            }
            else return new BaseResult(202,"库存不够或者重试次数达到上限");




    }

往返票

 @Transactional
    public BaseResult creatTwoOrder(FlightOrderServiceImpl orderService,List> passengers,Map selectFlightMap,String account) throws Exception {


            //            座位
            int k1=0,k2=0;
            FlightSeat seat = seatService.getById(selectFlightMap.get("goSeatId"));
            FlightSeat seatback = seatService.getById(selectFlightMap.get("backSeatId"));


            //先判断库存
            if(seat.getRestNum()<1||seatback.getRestNum()<1){
                return new BaseResult(201,"库存不够了");
            }

            //如果库存都够
            seat.setRestNum(seat.getRestNum()-1);
            boolean updateResult = seatService.updateById(seat);
            if(!updateResult){//如果更新失败
                int max =5;
                int cnt=0;
                while(cnt pas : passengers) {
                    FlightPassenger passenger = new FlightPassenger();
                    passenger.setOrderId(Order.getOrderId());
                    passenger.setName(pas.get("name"));
                    passenger.setIdentityId(pas.get("sfz"));
                    passenger.setPhone(pas.get("phone"));
                    passengerService.save(passenger);
                }

                return new BaseResult(200,"支付成功",Order.getOrderId());
            }
            else {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return new BaseResult(202, "库存不够或者达到重试次数上限");

            }


    }

你可能感兴趣的:(java,前端,javascript)