12.23软工踩坑

12.23软工踩坑

这里应该是alterRoomNumber

image-20241223232643208

image-20241224002339840

这段代码也有问题

要加一句

如下:

        if (waitqueueThis.getIsWaiting()==1){
            //如果在等待中,更新等待时间
            Date lastRequestTime = waitqueueThis.getLastRequestTime();
            LocalDateTime nowTime = LocalDateTime.now();
            LocalDateTime lastRequestTimeLocal = LocalDateTime.ofInstant(lastRequestTime.toInstant(), ZoneId.systemDefault());
            Duration duration = Duration.between(lastRequestTimeLocal, nowTime);
            long seconds = duration.toSeconds();
            waitqueueService.lambdaUpdate().eq(Waitqueue::getRoomNum, room_number)
                    .set(Waitqueue::getWaitingTime, waitqueueThis.getWaitingTime().add(BigDecimal.valueOf(seconds)))
                    .set(Waitqueue::getLastRequestTime,new Date())
                    .update();
        }

我们看下面这段代码,里面藏着一个很隐蔽的问题

@Override
public StatusRsp getAirconditioner(Long room_number) {
    int totalUsingNum = 0;
    Airconditioner airconditioner = this.lambdaQuery().eq(Airconditioner::getId, room_number).one();
    Room room = roomService.lambdaQuery().eq(Room::getRoomNumber, room_number).one();
    Waitqueue waitqueueThis = waitqueueService.lambdaQuery().eq(Waitqueue::getRoomNum, room_number).one();
    if (waitqueueThis.getIsWaiting() == 1) {
        //如果在等待中,更新等待时间
        Date lastRequestTime = waitqueueThis.getLastRequestTime();
        LocalDateTime nowTime = LocalDateTime.now();
        LocalDateTime lastRequestTimeLocal = LocalDateTime.ofInstant(lastRequestTime.toInstant(), ZoneId.systemDefault());
        Duration duration = Duration.between(lastRequestTimeLocal, nowTime);
        long seconds = duration.toSeconds();
        waitqueueService.lambdaUpdate().eq(Waitqueue::getRoomNum, room_number)
                .set(Waitqueue::getWaitingTime, waitqueueThis.getWaitingTime().add(BigDecimal.valueOf(seconds)))
                .set(Waitqueue::getLastRequestTime, new Date())
                .update();
    }
    List<Airconditioner> airconditionerList = this.lambdaQuery().list();
    int rate = airconditioner.getSpeed();
    //如果使用空调数小于3,则可以将等待队列中的空调启动
    for (Airconditioner airconditioner1 : airconditionerList) {
        if (airconditioner1.getPower() == 1) {
            totalUsingNum++;
        }
    }
    List<Waitqueue> list = waitqueueService.lambdaQuery().eq(Waitqueue::getIsWaiting, 1)
            .orderBy(true, false, Waitqueue::getLastRequestTime)
            .list();
    List<Airconditioner> usingACList = this.lambdaQuery()
            .eq(Airconditioner::getPower, 1)
            .orderBy(true, false, Airconditioner::getAcUsageTime)
            .list();
    String alterRoomNumber = null;
    if (usingACList.size() > 0) {
        Airconditioner alterAC = usingACList.get(0);
        alterRoomNumber = alterAC.getRoomId();
    }
    int size = list.size();//等待中的空调数量
    if (totalUsingNum < 3 && size > 0) {
        int canUseNum = 3 - totalUsingNum;
        log.info("等待队列中的空调(按照上次调用时间降序):{}", list);
        for (int i = 0; i < Math.min(canUseNum, size); i++) {
            int num = list.get(i).getRoomNum();
            //将等待时间超过20s的空调开启,并且移出等待队列
            this.lambdaUpdate().eq(Airconditioner::getId, num)
                    .set(Airconditioner::getPower, 1)
                    .update();
            waitqueueService.lambdaUpdate().eq(Waitqueue::getRoomNum, num)
                    .set(Waitqueue::getIsWaiting, 0)
                    .set(Waitqueue::getWaitingTime, BigDecimal.valueOf(0))
                    .update();
        }
    }
    //如果超过三个空调在使用中,需要一个调度算法,找到等待时间超过20s的空调,换掉总使用时间最长的空调
    if (totalUsingNum == 3 && size > 0) {
        for (Waitqueue waitRoom : list) {
            if (waitRoom.getWaitingTime().compareTo(BigDecimal.valueOf(20)) > 0) {
                //找到等待时间超过20s的空调,开启
                int num = waitRoom.getRoomNum();
                this.lambdaUpdate().eq(Airconditioner::getId, num)
                        .set(Airconditioner::getPower, 1)
                        .set(Airconditioner::getQueue,0)
                        .update();
                waitqueueService.lambdaUpdate().eq(Waitqueue::getRoomNum, num)
                        .set(Waitqueue::getIsWaiting, 0)
                        .set(Waitqueue::getWaitingTime, BigDecimal.valueOf(0))
                        .set(Waitqueue::getLastRequestTime,new Date())
                        .set(Waitqueue::getWaitingTime,0)
                        .update();
                //将使用时间最长的空调,关闭
                this.lambdaUpdate().eq(Airconditioner::getId, alterRoomNumber)
                        .set(Airconditioner::getPower, 0)
                        .set(Airconditioner::getQueue,1)
                        .update();
                waitqueueService.lambdaUpdate().eq(Waitqueue::getRoomNum, alterRoomNumber)
                        .set(Waitqueue::getIsWaiting, 1)
                        .set(Waitqueue::getWaitingTime, BigDecimal.valueOf(0))
                        .set(Waitqueue::getLastRequestTime,new Date())
                        .set(Waitqueue::getWaitingTime,0)
                        .update();
            }
        }
    }

    List<Waitqueue> waitqueueList = waitqueueService.lambdaQuery().list();
    if (airconditioner == null) {
        return null;
    }
    if (airconditioner.getPower() == 1) {
        //空调在使用过程中,实时计算费用
        LocalDateTime nowTime = LocalDateTime.now();
        Date lastStartTime = airconditioner.getLastStartTime();
        LocalDateTime lastAcUseTime = LocalDateTime.ofInstant(lastStartTime.toInstant(), ZoneId.systemDefault());
        Duration duration = Duration.between(lastAcUseTime, nowTime);
        //计算空调距离数据库中的lastUseTime到现在的时间差
        long seconds = duration.toSeconds();
        //log.info("距离上次使用的秒数:{}", seconds);
        BigDecimal fee = BigDecimal.valueOf(1.0 * seconds * airconditioner.getSpeed() / 3 / 60);
        //room更新费用
        room.setAcFee(room.getAcFee().add(fee));
        room.setAcUsageTime(room.getAcUsageTime().add(BigDecimal.valueOf(1.0 * seconds / 3 / 60)));
        room.setTotalFee(room.getTotalFee().add(fee));
        if (room.getCurrentTemperature().compareTo(airconditioner.getTemperature()) < 0) {
            //房间温度小于设定温度
            room.setCurrentTemperature(room.getCurrentTemperature().add(BigDecimal.valueOf(1.0 * seconds / 60)));
        } else {
            //房间温度大于设定温度
            BigDecimal subtract = room.getCurrentTemperature().subtract(BigDecimal.valueOf(1.0 * seconds / 60));
            room.setCurrentTemperature(room.getCurrentTemperature().subtract(BigDecimal.valueOf(1.0 * seconds / 60)));
        }
        roomService.lambdaUpdate().eq(Room::getRoomNumber, room_number).update(room);
        //airconditioner更新使用时间
        airconditioner.setLastStartTime(new Date());
        this.lambdaUpdate().eq(Airconditioner::getId, room_number).update(airconditioner);
    } else {
        //空调未使用,更新房间温度
        if (room.getCurrentTemperature().compareTo(BigDecimal.valueOf(room.getEnvironmentTemperature())) < 0) {
            //房间温度小于环境温度
            roomService.lambdaUpdate().eq(Room::getRoomNumber, room_number)
                    .set(Room::getCurrentTemperature,
                            room.getCurrentTemperature().add(BigDecimal.valueOf(RateEnums.getEnumByValue(rate).getText() / 60)));
        } else {
            //房间温度大于环境温度
            roomService.lambdaUpdate().eq(Room::getRoomNumber, room_number)
                    .set(Room::getCurrentTemperature,
                            room.getCurrentTemperature().subtract(BigDecimal.valueOf((RateEnums.getEnumByValue(rate).getText() / 60))));
        }
    }
    StatusRsp result = new StatusRsp();
    result.setMode(airconditioner.getMode());
    result.setSpeed(SpeedEnums.getEnumByValue(airconditioner.getSpeed()).getText());
    result.setPower((airconditioner.getPower() == 1));
    result.setCost(room.getAcFee());
    //queue里面
    result.setQueue(String.valueOf(waitqueueThis.getIsWaiting()));
    result.setTime(room.getAcUsageTime());
    return result;
}
}

问题就出在115行的代码

this.lambdaUpdate().eq(Airconditioner::getId, room_number).update(airconditioner);

本意是想计算出空调使用的时间然后计算费用加到总计费上面,但是用了update(airconditioner),这就出大问题了,因为airconditioner我们是从数据库中查出来的,但是呢,在上面的语句中我们有一个调度的逻辑,也就是说我们可能已经把数据库中空调的开关状态改变了,但是这里又把它还原了!

posted @ 2024-12-24 20:56  vast_joy  阅读(1)  评论(0编辑  收藏  举报