From a0204eff8fafa2df05c2237026a9dcf042da2ab3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=83=91=E6=97=AD=E6=98=8E=5C73939?= <739390650@QQ.COM> Date: Mon, 8 Dec 2025 15:05:40 +0800 Subject: [PATCH] =?UTF-8?q?fix:=E9=87=8D=E5=A4=8D=E5=88=86=E9=85=8D?= =?UTF-8?q?=E9=97=AE=E9=A2=98=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wms/ext/fab/controller/FabController.java | 6 +- .../point/service/ISchBasePointService.java | 3 +- .../service/impl/SchBasePointServiceImpl.java | 407 ++++++++++++------ .../sch/task_manage/task/core/TaskStatus.java | 28 ++ .../task/tasks/auto/GHCQLTask.java | 2 +- .../task/tasks/handheld/BlankingTask.java | 8 +- .../task/tasks/handheld/MtTask.java | 7 +- .../task/tasks/handheld/RackTask.java | 7 +- .../tasks/pcoperation/ProcessingSMTTask.java | 3 +- 9 files changed, 318 insertions(+), 153 deletions(-) diff --git a/lms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/ext/fab/controller/FabController.java b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/ext/fab/controller/FabController.java index 1916268..161b0ca 100644 --- a/lms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/ext/fab/controller/FabController.java +++ b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/ext/fab/controller/FabController.java @@ -245,20 +245,20 @@ public class FabController { if (REGION_CODE.get("内部加工").equals(materInfo.getPoint_code())) { List mater = materInfo.getMater(); if (CollUtil.isEmpty(mater)) throw new BadRequestException("物料信息为空,请确认!"); - SchBasePoint schBasePoint = iSchBasePointService.selectGroundByRegionCode(RegionEnum.NBJG.getRegion_code(), GoodsEnum.OUT_OF_STOCK.getValue()); + SchBasePoint schBasePoint = iSchBasePointService.selectGroundByRegionCode(RegionEnum.NBJG.getRegion_code(), GoodsEnum.OUT_OF_STOCK.getValue(),false); if (ObjectUtil.isEmpty(schBasePoint)) { throw new BadRequestException("仓库收货区域点位已满请清理"); } toJSON.put("material_info", mater); toJSON.put("region_code", RegionEnum.NBJG.getRegion_code()); } else if (REGION_CODE.get("外协加工").equals(materInfo.getPoint_code())) { - SchBasePoint schBasePoint = iSchBasePointService.selectGroundByRegionCode(RegionEnum.WXJG.getRegion_code(), GoodsEnum.OUT_OF_STOCK.getValue()); + SchBasePoint schBasePoint = iSchBasePointService.selectGroundByRegionCode(RegionEnum.WXJG.getRegion_code(), GoodsEnum.OUT_OF_STOCK.getValue(),false); if (ObjectUtil.isEmpty(schBasePoint)) { throw new BadRequestException("外协加工区域点位已满请清理"); } toJSON.put("region_code", RegionEnum.WXJG.getRegion_code()); } else if (REGION_CODE.get("内部过道").equals(materInfo.getPoint_code())) { - SchBasePoint schBasePoint = iSchBasePointService.selectGroundByRegionCode(RegionEnum.NBGD.getRegion_code(), GoodsEnum.OUT_OF_STOCK.getValue()); + SchBasePoint schBasePoint = iSchBasePointService.selectGroundByRegionCode(RegionEnum.NBGD.getRegion_code(), GoodsEnum.OUT_OF_STOCK.getValue(),false); if (ObjectUtil.isEmpty(schBasePoint)) { throw new BadRequestException("内部过道区域点位已满请清理"); } diff --git a/lms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch/point/service/ISchBasePointService.java b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch/point/service/ISchBasePointService.java index 402411d..600bb02 100644 --- a/lms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch/point/service/ISchBasePointService.java +++ b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch/point/service/ISchBasePointService.java @@ -120,6 +120,7 @@ public interface ISchBasePointService extends IService { */ SchBasePoint selectByReassign(String region_code, String vehicleCode); + /** * 根据区域及托盘类型获取库存信息 * @@ -191,7 +192,7 @@ public interface ISchBasePointService extends IService { * @param targetRegionCode * @param value */ - SchBasePoint selectGroundByRegionCode(String targetRegionCode, String value); + SchBasePoint selectGroundByRegionCode(String targetRegionCode, String value, Boolean isLock); /** * 选择登录设备 diff --git a/lms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch/point/service/impl/SchBasePointServiceImpl.java b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch/point/service/impl/SchBasePointServiceImpl.java index 39e1dfd..cfc9fc3 100644 --- a/lms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch/point/service/impl/SchBasePointServiceImpl.java +++ b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch/point/service/impl/SchBasePointServiceImpl.java @@ -2,6 +2,7 @@ package org.nl.wms.sch.point.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.DateField; import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUtil; import cn.hutool.core.lang.Assert; @@ -49,11 +50,10 @@ import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; -import java.lang.reflect.Type; import java.util.*; -import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; + /** * @author lyd * @description 服务实现 @@ -164,8 +164,9 @@ public class SchBasePointServiceImpl extends ServiceImpl schBasePoints = pointMapper.selectList(Wrappers.lambdaQuery(SchBasePoint.class) .eq(SchBasePoint::getIs_lock, false) .isNull(SchBasePoint::getVehicle_code) .eq(SchBasePoint::getPoint_type, pointType) - .eq(StrUtil.isNotEmpty(regionCode),SchBasePoint::getRegion_code, regionCode) + .eq(StrUtil.isNotEmpty(regionCode), SchBasePoint::getRegion_code, regionCode) .eq(SchBasePoint::getPoint_status, GoodsEnum.OUT_OF_STOCK.getValue()) .eq(SchBasePoint::getCan_vehicle_type, mdBaseVehicle.getVehicle_type()) - .eq(SchBasePoint::getIs_used, true)); + .eq(SchBasePoint::getIs_used, true) + // 修复4:添加行锁+LIMIT 1 + .last("LIMIT 1 FOR UPDATE")); if (CollUtil.isNotEmpty(schBasePoints) && schBasePoints.size() > 0) { SchBasePoint schBasePoint = schBasePoints.get(0); schBasePoint.setIs_lock(true); @@ -295,6 +301,7 @@ public class SchBasePointServiceImpl extends ServiceImpl 0) { SchBasePoint schBasePoint1 = schBasePoints.get(0); SchBasePoint schBasePoint = pointMapper.selectById(schBasePoint1.getNext_wait_point()); @@ -334,7 +344,9 @@ public class SchBasePointServiceImpl extends ServiceImpl 0) { SchBasePoint schBasePoint1 = schBasePoints1.get(0); SchBasePoint schBasePoint = pointMapper.selectById(schBasePoint1.getNext_wait_point()); @@ -348,14 +360,18 @@ public class SchBasePointServiceImpl extends ServiceImpl schBasePoints = pointMapper.selectList(Wrappers.lambdaQuery(SchBasePoint.class) .eq(SchBasePoint::getNext_wait_point, device_code) .eq(SchBasePoint::getIs_used, true) .eq(SchBasePoint::getIs_lock, false).isNull(SchBasePoint::getVehicle_code) - .eq(SchBasePoint::getPoint_status, GoodsEnum.OUT_OF_STOCK.getValue())); + .eq(SchBasePoint::getPoint_status, GoodsEnum.OUT_OF_STOCK.getValue()) + // 修复7:添加行锁+LIMIT 1 + .last("LIMIT 1 FOR UPDATE")); if (CollUtil.isNotEmpty(schBasePoints) && schBasePoints.size() > 0) { SchBasePoint schBasePoint = schBasePoints.get(0); schBasePoint.setVehicle_code(vehicleCode); @@ -367,15 +383,20 @@ public class SchBasePointServiceImpl extends ServiceImpl schBasePoints = pointMapper.selectList(Wrappers.lambdaQuery(SchBasePoint.class) .eq(SchBasePoint::getIs_lock, false) .isNotNull(SchBasePoint::getVehicle_code) .eq(SchBasePoint::getPoint_status, GoodsEnum.EMPTY_PALLETS.getValue()) - .eq(SchBasePoint::getCan_vehicle_type, vehicle_type)); + .eq(SchBasePoint::getCan_vehicle_type, vehicle_type) + // 修复8:添加行锁+LIMIT 1 + .last("LIMIT 1 FOR UPDATE")); if (CollectionUtils.isEmpty(schBasePoints)) { return null; } @@ -385,115 +406,172 @@ public class SchBasePointServiceImpl extends ServiceImpl schBasePoints = pointMapper.selectList(Wrappers.lambdaQuery(SchBasePoint.class) .eq(SchBasePoint::getIs_lock, false) .eq(SchBasePoint::getIs_used, true) .eq(SchBasePoint::getPoint_status, GoodsEnum.OUT_OF_STOCK.getValue()) .eq(SchBasePoint::getCan_vehicle_type, vehicle_type) - .isNull(SchBasePoint::getVehicle_code)); + .isNull(SchBasePoint::getVehicle_code) + // 修复9:添加行锁+LIMIT 1 + .last("LIMIT 1 FOR UPDATE")); return (CollUtil.isNotEmpty(schBasePoints) && schBasePoints.size() > 0) ? schBasePoints.get(0) : null; } + } + // 修复10:调整事务与锁顺序 - 外层锁,内部事务方法 @Override public SchBasePoint selectByGroundPoint(String region_code, String pointStatus, String vehicle_type, int seq, int point_type) { + synchronized (SchBasePointServiceImpl.class) { + return transactionalSelectByGroundPoint(region_code, pointStatus, vehicle_type, seq, point_type); + } + } + + // 抽取事务逻辑到私有方法 + @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW) + public SchBasePoint transactionalSelectByGroundPoint(String region_code, String pointStatus, String vehicle_type, int seq, int point_type) { + // 2. 构建查询条件(抽取公共方法) + LambdaQueryWrapper wrapper = buildQueryWrapper(region_code, pointStatus, vehicle_type, seq, point_type, true); + wrapper.last("LIMIT 1 FOR UPDATE"); // 加行锁+限制1条 + SchBasePoint schBasePoint = pointMapper.selectOne(wrapper); + + // 3. 降级查询 + if (schBasePoint == null) { + log.warn("带region_code[{}]查询点位为空,降级查询(忽略region_code)", region_code); + wrapper = buildQueryWrapper(region_code, pointStatus, vehicle_type, seq, point_type, false); + wrapper.last("LIMIT 1 FOR UPDATE"); + schBasePoint = pointMapper.selectOne(wrapper); + } + + // 4. 锁定点位 + if (schBasePoint != null) { + schBasePoint.setIs_lock(true); + PointUtils.setUpdateByAcs(schBasePoint); + int updateCount = pointMapper.updateById(schBasePoint); + if (updateCount == 0) { + log.error("点位[{}]锁定失败,可能已被其他线程修改", schBasePoint.getPoint_code()); + throw new RuntimeException("点位锁定失败"); + } + log.info("成功锁定点位:{},region_code:{}", schBasePoint.getPoint_code(), schBasePoint.getRegion_code()); + return schBasePoint; + } + + log.warn("未查询到可用点位,参数:region_code={}, vehicle_type={}, seq={}", region_code, vehicle_type, seq); + return null; + } + + // 抽取公共查询条件 + private LambdaQueryWrapper buildQueryWrapper(String regionCode, String pointStatus, String vehicleType, int seq, int pointType, boolean includeRegionCode) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(SchBasePoint.class) + .eq(SchBasePoint::getIs_lock, false) + .eq(SchBasePoint::getIs_used, true) + .eq(SchBasePoint::getPoint_status, pointStatus); + + // 明确拆分条件,提升可读性 + if (!"G01".equals(vehicleType)) { + wrapper.eq(SchBasePoint::getPoint_type, "1"); + } else { + wrapper.eq(SchBasePoint::getPoint_type, pointType); + } + if (StrUtil.isNotBlank(vehicleType)) { + wrapper.eq(SchBasePoint::getCan_vehicle_type, vehicleType); + } + if (seq == 2) { + wrapper.isNull(SchBasePoint::getVehicles) + .orderByAsc(SchBasePoint::getIn_order_seq); + } else if (seq == 1) { + wrapper.isNull(SchBasePoint::getVehicle_code); + } + if (includeRegionCode && StrUtil.isNotBlank(regionCode)) { + wrapper.eq(SchBasePoint::getRegion_code, regionCode); + } + return wrapper; + } + + // 修复11:调整事务与锁顺序 - 外层锁,内部事务方法 + @Override + public SchBasePoint selectByEmptyCage(String region_code, String vehicle_type, String pointStatus, boolean isVehicle, SchBaseTask task) { + synchronized (SchBasePointServiceImpl.class) { + return transactionalSelectByEmptyCage(region_code, vehicle_type, pointStatus, isVehicle, task); + } + } + + // 抽取事务逻辑到私有方法 + @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW) + public SchBasePoint transactionalSelectByEmptyCage(String region_code, String vehicle_type, String pointStatus, boolean isVehicle, SchBaseTask task) { List schBasePoints = pointMapper.selectList(Wrappers.lambdaQuery(SchBasePoint.class) .eq(SchBasePoint::getIs_lock, false) .eq(SchBasePoint::getIs_used, true) .eq(SchBasePoint::getPoint_status, pointStatus) - .eq(!vehicle_type.equals("G01"), SchBasePoint::getPoint_type, "1") - .eq(vehicle_type.equals("G01"), SchBasePoint::getPoint_type, point_type) - .eq(StrUtil.isNotBlank(vehicle_type), SchBasePoint::getCan_vehicle_type, vehicle_type) - .isNull(seq == 2, SchBasePoint::getVehicles) - .isNull(seq == 1, SchBasePoint::getVehicle_code) - .eq(StrUtil.isNotBlank(region_code), SchBasePoint::getRegion_code, region_code) - .orderByAsc(seq == 2, SchBasePoint::getIn_order_seq)); - if (CollUtil.isEmpty(schBasePoints)) { - schBasePoints = pointMapper.selectList(Wrappers.lambdaQuery(SchBasePoint.class) - .eq(SchBasePoint::getIs_lock, false) - .eq(SchBasePoint::getIs_used, true) - .eq(SchBasePoint::getPoint_status, pointStatus) - .eq(!vehicle_type.equals("G01"), SchBasePoint::getPoint_type, "1") - .eq(vehicle_type.equals("G01"), SchBasePoint::getPoint_type, point_type) - .eq(StrUtil.isNotBlank(vehicle_type), SchBasePoint::getCan_vehicle_type, vehicle_type) - .isNull(seq == 2, SchBasePoint::getVehicles) - .isNull(seq == 1, SchBasePoint::getVehicle_code) - .orderByAsc(seq == 2, SchBasePoint::getIn_order_seq)); + .eq(SchBasePoint::getCan_vehicle_type, vehicle_type) + .isNotNull(SchBasePoint::getVehicle_code) + .orderByDesc(SchBasePoint::getIn_order_seq) + // 修复12:添加行锁+LIMIT 1 + .last("LIMIT 1 FOR UPDATE")); + if (CollUtil.isNotEmpty(schBasePoints) && schBasePoints.size() > 0) { + SchBasePoint schBasePoint = schBasePoints.get(0); + schBasePoint.setIs_lock(true); + PointUtils.setUpdateByAcs(schBasePoint); + updateById(schBasePoint); + return schBasePoint; } - return (CollUtil.isNotEmpty(schBasePoints) && schBasePoints.size() > 0) ? schBasePoints.get(0) : null; + schBasePoints = pointMapper.selectList(Wrappers.lambdaQuery(SchBasePoint.class) + .eq(SchBasePoint::getIs_lock, false) + .eq(SchBasePoint::getIs_used, true) + .eq(SchBasePoint::getPoint_status, pointStatus) + .eq(SchBasePoint::getCan_vehicle_type, vehicle_type) + .eq(SchBasePoint::getRegion_code, region_code) + .isNotNull(SchBasePoint::getVehicles) + .orderByDesc(SchBasePoint::getIn_order_seq) + // 修复13:添加行锁+LIMIT 1 + .last("LIMIT 1 FOR UPDATE")); + if (CollUtil.isNotEmpty(schBasePoints) && schBasePoints.size() > 0) { + SchBasePoint schBasePoint = schBasePoints.get(0); + List msg = new ArrayList<>(); + String vehicles = schBasePoint.getVehicles(); + boolean contains = vehicles.contains(","); + if (contains) { + String[] split = vehicles.split(","); + msg = Arrays.asList(split); + } else { + msg.add(vehicles); + } + Integer vehicle_qty = schBasePoint.getVehicle_qty(); + if (vehicle_qty != msg.size()) throw new BadRequestException("载具数量与载具编码数量不一致!"); + String s = msg.get(msg.size() - 1); + schBasePoint.setVehicle_qty(vehicle_qty - 1); + msg.remove(s); + schBasePoint.setVehicles(JSONUtil.toJsonStr(msg)); + this.updateById(schBasePoint); + if (schBasePoint.getVehicle_qty() == 0) { + update(Wrappers.lambdaUpdate(SchBasePoint.class) + .eq(SchBasePoint::getPoint_code, schBasePoint.getPoint_code()) + .set(SchBasePoint::getPoint_status, GoodsEnum.OUT_OF_STOCK.getValue()) + .set(SchBasePoint::getVehicles, null)); + } + SchBasePoint schBasePoint1 = null; + if (vehicle_qty == 1) { + schBasePoint1 = selectByPointCode(schBasePoint.getPoint_code()); + } else { + schBasePoint1 = selectByPointCode(schBasePoint.getPoint_code() + "_" + (vehicle_qty - 1)); + } + if (ObjectUtil.isEmpty(schBasePoint1)) throw new BadRequestException("该货位不存在!"); + schBasePoint1.setVehicle_code(s); + schBasePoint1.setIs_lock(true); + PointUtils.setUpdateByAcs(schBasePoint1); + updateById(schBasePoint1); + return schBasePoint1; + } + return null; } + // 修复14:修改方法添加synchronized @Override - @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW) - public SchBasePoint selectByEmptyCage(String region_code, String vehicle_type, String pointStatus, boolean isVehicle, SchBaseTask task) { - synchronized (lock) { - List schBasePoints = pointMapper.selectList(Wrappers.lambdaQuery(SchBasePoint.class) - .eq(SchBasePoint::getIs_lock, false) - .eq(SchBasePoint::getIs_used, true) - .eq(SchBasePoint::getPoint_status, pointStatus) - .eq(SchBasePoint::getCan_vehicle_type, vehicle_type) - .isNotNull(SchBasePoint::getVehicle_code) - .orderByDesc(SchBasePoint::getIn_order_seq)); - if (CollUtil.isNotEmpty(schBasePoints) && schBasePoints.size() > 0) { - SchBasePoint schBasePoint = schBasePoints.get(0); - schBasePoint.setIs_lock(true); - PointUtils.setUpdateByAcs(schBasePoint); - updateById(schBasePoint); - return schBasePoint; - } - schBasePoints = pointMapper.selectList(Wrappers.lambdaQuery(SchBasePoint.class) - .eq(SchBasePoint::getIs_lock, false) - .eq(SchBasePoint::getIs_used, true) - .eq(SchBasePoint::getPoint_status, pointStatus) - .eq(SchBasePoint::getCan_vehicle_type, vehicle_type) - .eq(SchBasePoint::getRegion_code, region_code) - .isNotNull(SchBasePoint::getVehicles) - .orderByDesc(SchBasePoint::getIn_order_seq)); - if (CollUtil.isNotEmpty(schBasePoints) && schBasePoints.size() > 0) { - SchBasePoint schBasePoint = schBasePoints.get(0); - List msg = new ArrayList<>(); - String vehicles = schBasePoint.getVehicles(); - boolean contains = vehicles.contains(","); - if (contains) { - String[] split = vehicles.split(","); - msg = Arrays.asList(split); - } else { - msg.add(vehicles); - } - Integer vehicle_qty = schBasePoint.getVehicle_qty(); - if (vehicle_qty != msg.size()) throw new BadRequestException("载具数量与载具编码数量不一致!"); - String s = msg.get(msg.size() - 1); - schBasePoint.setVehicle_qty(vehicle_qty - 1); - msg.remove(s); - schBasePoint.setVehicles(JSONUtil.toJsonStr(msg)); - this.updateById(schBasePoint); - if (schBasePoint.getVehicle_qty() == 0) { - update(Wrappers.lambdaUpdate(SchBasePoint.class) - .eq(SchBasePoint::getPoint_code, schBasePoint.getPoint_code()) - .set(SchBasePoint::getPoint_status, GoodsEnum.OUT_OF_STOCK.getValue()) - .set(SchBasePoint::getVehicles, null)); - } - SchBasePoint schBasePoint1 = null; - if (vehicle_qty == 1) { - schBasePoint1 = selectByPointCode(schBasePoint.getPoint_code()); - } else { - schBasePoint1 = selectByPointCode(schBasePoint.getPoint_code() + "_" + (vehicle_qty - 1)); - } - if (ObjectUtil.isEmpty(schBasePoint1)) throw new BadRequestException("该货位不存在!"); - schBasePoint1.setVehicle_code(s); - schBasePoint1.setIs_lock(true); - PointUtils.setUpdateByAcs(schBasePoint1); - updateById(schBasePoint1); - return schBasePoint1; - } - return null; - } - } - - @Override - public void updatePointLock(String region_code, Boolean lock) { + public synchronized void updatePointLock(String region_code, Boolean lock) { update(Wrappers.lambdaUpdate(SchBasePoint.class) .eq(SchBasePoint::getRegion_code, region_code) .set(SchBasePoint::getIs_lock, lock)); @@ -505,15 +583,55 @@ public class SchBasePointServiceImpl extends ServiceImpl schBasePoints = pointMapper.selectList(Wrappers.lambdaQuery(SchBasePoint.class) + @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW) + public SchBasePoint selectGroundByRegionCode(String targetRegionCode, String pointStatus, Boolean isLock) { + // ========== 1. 参数合法性校验(提前拦截无效请求) ========== + Assert.notNull(pointStatus, "点位状态(pointStatus)不能为空"); + Assert.notNull(isLock, "是否锁定标识(isLock)不能为空"); + log.info("[按区域查地面点位] 开始查询,目标区域编码:{},点位状态:{},是否锁定:{}", + targetRegionCode, pointStatus, isLock); + + // ========== 2. 构建查询条件(优化可读性,加行锁+LIMIT 1) ========== + LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery(SchBasePoint.class) .eq(SchBasePoint::getIs_lock, false) .eq(SchBasePoint::getIs_used, true) - .eq(SchBasePoint::getPoint_status, value) + .eq(SchBasePoint::getPoint_status, pointStatus) .isNull(SchBasePoint::getVehicle_code) - .eq(StrUtil.isNotBlank(targetRegionCode), SchBasePoint::getRegion_code, targetRegionCode) - .orderByAsc(SchBasePoint::getIn_order_seq)); - return (CollUtil.isNotEmpty(schBasePoints) && schBasePoints.size() > 0) ? schBasePoints.get(0) : null; + .orderByAsc(SchBasePoint::getIn_order_seq); + + // 优化动态条件:拆分if-else,提升可读性(替代原eq(StrUtil.isNotBlank(...))) + if (StrUtil.isNotBlank(targetRegionCode)) { + queryWrapper.eq(SchBasePoint::getRegion_code, targetRegionCode); + } + + // 核心优化:LIMIT 1 避免全量查询 + FOR UPDATE 加行锁(保障并发安全) + queryWrapper.last("LIMIT 1 FOR UPDATE"); + + // ========== 3. 执行查询(仅查1条,性能最优) ========== + SchBasePoint targetPoint = pointMapper.selectOne(queryWrapper); + if (targetPoint == null) { + log.warn("[按区域查地面点位] 未查询到可用点位,目标区域编码:{},点位状态:{}", targetRegionCode, pointStatus); + return null; + } + + // ========== 4. 按需锁定点位(校验更新结果,避免假锁定) ========== + if (Boolean.TRUE.equals(isLock)) { + targetPoint.setIs_lock(true); + PointUtils.setUpdateByAcs(targetPoint); + int updateCount = pointMapper.updateById(targetPoint); + + // 校验更新结果:更新失败则抛异常触发事务回滚 + if (updateCount == 0) { + log.error("[按区域查地面点位] 点位锁定失败,点位编码:{}", targetPoint.getPoint_code()); + throw new RuntimeException("点位锁定失败,点位编码:" + targetPoint.getPoint_code()); + } + log.info("[按区域查地面点位] 点位锁定成功,点位编码:{},区域编码:{}", + targetPoint.getPoint_code(), targetPoint.getRegion_code()); + } else { + log.info("[按区域查地面点位] 无需锁定,返回点位:{}", targetPoint.getPoint_code()); + } + + return targetPoint; } @Override @@ -588,7 +706,7 @@ public class SchBasePointServiceImpl extends ServiceImpl 0) { SchBasePoint schBasePoint = schBasePoints.get(0); schBasePoint.setIs_lock(true); @@ -612,7 +732,9 @@ public class SchBasePointServiceImpl extends ServiceImpl schBasePoints = pointMapper.selectList(Wrappers.lambdaQuery(SchBasePoint.class) .eq(SchBasePoint::getIs_lock, false) .eq(SchBasePoint::getIs_used, true) @@ -622,7 +744,9 @@ public class SchBasePointServiceImpl extends ServiceImpl 0) ? schBasePoints.get(0) : null; if (ObjectUtil.isNotEmpty(schBasePoint)) { schBasePoint.setIs_lock(true); @@ -631,6 +755,7 @@ public class SchBasePointServiceImpl extends ServiceImpl getStructList(String pointCode, String vehicle_type) { @@ -657,7 +782,7 @@ public class SchBasePointServiceImpl extends ServiceImpl collect = structList.stream().collect(Collectors.groupingBy( OrderMater::getVehicle_code, @@ -679,34 +804,44 @@ public class SchBasePointServiceImpl extends ServiceImpl schBasePoints = pointMapper.selectList(Wrappers.lambdaQuery(SchBasePoint.class) - .eq(SchBasePoint::getIs_lock, false) - .isNotNull(SchBasePoint::getVehicle_code) - .eq(StrUtil.isNotEmpty(region_code), SchBasePoint::getRegion_code, region_code) - .eq(SchBasePoint::getPoint_status, GoodsEnum.EMPTY_PALLETS.getValue()) - .eq(SchBasePoint::getCan_vehicle_type, vehicleType) - .eq(SchBasePoint::getIs_used, true)); - if (CollectionUtils.isEmpty(schBasePoints)) { - schBasePoints = pointMapper.selectList(Wrappers.lambdaQuery(SchBasePoint.class) - .eq(SchBasePoint::getIs_lock, false) - .isNotNull(SchBasePoint::getVehicle_code) - .eq(SchBasePoint::getPoint_status, GoodsEnum.EMPTY_PALLETS.getValue()) - .eq(SchBasePoint::getCan_vehicle_type, vehicleType) - .eq(SchBasePoint::getIs_used, true)); - } - if (schBasePoints.size() == 0) { - return null; - } - SchBasePoint schBasePoint = schBasePoints.get(0); - schBasePoint.setIs_lock(true); - PointUtils.setUpdateByAcs(schBasePoint); - pointMapper.updateById(schBasePoint); - return schBasePoint; + synchronized (SchBasePointServiceImpl.class) { + return transactionalSelectEmpVehicleByRegionCode(region_code, vehicleType); } } + + // 抽取事务逻辑到私有方法 + @Transactional(propagation = Propagation.REQUIRES_NEW) + public SchBasePoint transactionalSelectEmpVehicleByRegionCode(String region_code, String vehicleType) { + //查询满足条件的站点 + List schBasePoints = pointMapper.selectList(Wrappers.lambdaQuery(SchBasePoint.class) + .eq(SchBasePoint::getIs_lock, false) + .isNotNull(SchBasePoint::getVehicle_code) + .eq(StrUtil.isNotEmpty(region_code), SchBasePoint::getRegion_code, region_code) + .eq(SchBasePoint::getPoint_status, GoodsEnum.EMPTY_PALLETS.getValue()) + .eq(SchBasePoint::getCan_vehicle_type, vehicleType) + .eq(SchBasePoint::getIs_used, true) + // 修复18:添加行锁+LIMIT 1 + .last("LIMIT 1 FOR UPDATE")); + if (CollectionUtils.isEmpty(schBasePoints)) { + schBasePoints = pointMapper.selectList(Wrappers.lambdaQuery(SchBasePoint.class) + .eq(SchBasePoint::getIs_lock, false) + .isNotNull(SchBasePoint::getVehicle_code) + .eq(SchBasePoint::getPoint_status, GoodsEnum.EMPTY_PALLETS.getValue()) + .eq(SchBasePoint::getCan_vehicle_type, vehicleType) + .eq(SchBasePoint::getIs_used, true) + // 修复19:添加行锁+LIMIT 1 + .last("LIMIT 1 FOR UPDATE")); + } + if (schBasePoints.size() == 0) { + return null; + } + SchBasePoint schBasePoint = schBasePoints.get(0); + schBasePoint.setIs_lock(true); + PointUtils.setUpdateByAcs(schBasePoint); + pointMapper.updateById(schBasePoint); + return schBasePoint; + } } diff --git a/lms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch/task_manage/task/core/TaskStatus.java b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch/task_manage/task/core/TaskStatus.java index 3772e46..09255ed 100644 --- a/lms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch/task_manage/task/core/TaskStatus.java +++ b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch/task_manage/task/core/TaskStatus.java @@ -45,4 +45,32 @@ public enum TaskStatus { public void setDesc(String desc) { this.desc = desc; } + + /** + * 根据code查找name + * @param code 状态码 + * @return 状态名称 + */ + public static String getNameByCode(String code) { + for (TaskStatus status : TaskStatus.values()) { + if (status.getCode().equals(code)) { + return status.getName(); + } + } + return null; + } + + /** + * 根据name查找code + * @param name 状态名称 + * @return 状态码 + */ + public static String getCodeByName(String name) { + for (TaskStatus status : TaskStatus.values()) { + if (status.getName().equals(name)) { + return status.getCode(); + } + } + return null; + } } diff --git a/lms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch/task_manage/task/tasks/auto/GHCQLTask.java b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch/task_manage/task/tasks/auto/GHCQLTask.java index e25dc9c..e534b34 100644 --- a/lms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch/task_manage/task/tasks/auto/GHCQLTask.java +++ b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch/task_manage/task/tasks/auto/GHCQLTask.java @@ -131,7 +131,7 @@ public class GHCQLTask extends AbstractTask { //任务创建后锁住终点 SchBasePoint nextPoint = pointService.getById(task.getPoint_code2()); nextPoint.setIng_task_code(task.getTask_code()); - pointService.updateById(point); + pointService.updateById(nextPoint); } /** diff --git a/lms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch/task_manage/task/tasks/handheld/BlankingTask.java b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch/task_manage/task/tasks/handheld/BlankingTask.java index 7e12e21..2355cc8 100644 --- a/lms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch/task_manage/task/tasks/handheld/BlankingTask.java +++ b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch/task_manage/task/tasks/handheld/BlankingTask.java @@ -93,10 +93,10 @@ public class BlankingTask extends AbstractTask { TaskUtils.setUpdateByAcs(task); taskService.updateById(task); - - schBasePoint.setIs_lock(true); - PointUtils.setUpdateByAcs(schBasePoint); - pointService.updateById(schBasePoint); + //锁定功能已经写在查询中,防止出现相同点位 + // schBasePoint.setIs_lock(true); + // PointUtils.setUpdateByAcs(schBasePoint); + // pointService.updateById(schBasePoint); } } diff --git a/lms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch/task_manage/task/tasks/handheld/MtTask.java b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch/task_manage/task/tasks/handheld/MtTask.java index 76e019a..0764966 100644 --- a/lms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch/task_manage/task/tasks/handheld/MtTask.java +++ b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch/task_manage/task/tasks/handheld/MtTask.java @@ -74,9 +74,10 @@ public class MtTask extends AbstractTask { TaskUtils.setUpdateByAcs(task); taskService.updateById(task); - schBasePoint.setIs_lock(true); - PointUtils.setUpdateByAcs(schBasePoint); - pointService.updateById(schBasePoint); + //锁定功能已经写在查询中,防止出现分配到相同点位,因此注释 + // schBasePoint.setIs_lock(true); + // PointUtils.setUpdateByAcs(schBasePoint); + // pointService.updateById(schBasePoint); } } diff --git a/lms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch/task_manage/task/tasks/handheld/RackTask.java b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch/task_manage/task/tasks/handheld/RackTask.java index 36c7d1b..83380f7 100644 --- a/lms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch/task_manage/task/tasks/handheld/RackTask.java +++ b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch/task_manage/task/tasks/handheld/RackTask.java @@ -84,9 +84,10 @@ public class RackTask extends AbstractTask { task.setTask_status(TaskStatus.CREATED.getCode()); TaskUtils.setUpdateByAcs(task); taskService.updateById(task); - schBasePoint.setIs_lock(true); - PointUtils.setUpdateByAcs(schBasePoint); - pointService.updateById(schBasePoint); + //锁定功能已经写在查询中,防止出现分配到相同点位,因此注释 + // schBasePoint.setIs_lock(true); + // PointUtils.setUpdateByAcs(schBasePoint); + // pointService.updateById(schBasePoint); } } diff --git a/lms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch/task_manage/task/tasks/pcoperation/ProcessingSMTTask.java b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch/task_manage/task/tasks/pcoperation/ProcessingSMTTask.java index 8dafdfa..1fcfaf5 100644 --- a/lms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch/task_manage/task/tasks/pcoperation/ProcessingSMTTask.java +++ b/lms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch/task_manage/task/tasks/pcoperation/ProcessingSMTTask.java @@ -105,7 +105,7 @@ public class ProcessingSMTTask extends AbstractTask { NoticeTypeEnum.WARN.getCode()); continue; } - SchBasePoint schBasePoint = schBasePointService.selectGroundByRegionCode(targetRegionCode, GoodsEnum.OUT_OF_STOCK.getValue()); + SchBasePoint schBasePoint = schBasePointService.selectGroundByRegionCode(targetRegionCode, GoodsEnum.OUT_OF_STOCK.getValue(),true); if (ObjectUtil.isEmpty(schBasePoint)) { task.setRemark("未找到所需点位!"); taskService.updateById(task); @@ -123,7 +123,6 @@ public class ProcessingSMTTask extends AbstractTask { taskService.updateById(task); //更新点位 - schBasePoint.setIs_lock(true); PointUtils.setUpdateByAcs(schBasePoint); pointService.updateById(schBasePoint); }