@@ -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<SchBasePointMapper, Sch
pointMapper . insert ( entity ) ;
}
// 修复1: 修改方法添加synchronized
@Override
public void update ( SchBasePoint entity ) {
public synchronized void update ( SchBasePoint entity ) {
String currentUserId = SecurityUtils . getCurrentUserId ( ) ;
String nickName = SecurityUtils . getCurrentNickName ( ) ;
String now = DateUtil . now ( ) ;
@@ -196,8 +197,9 @@ public class SchBasePointServiceImpl extends ServiceImpl<SchBasePointMapper, Sch
pointMapper . deleteBatchIds ( ids ) ;
}
// 修复2: 修改方法添加synchronized
@Override
public void changeUsed ( JSONObject jsonObject ) {
public synchronized void changeUsed ( JSONObject jsonObject ) {
// 不可能为空
JSONArray data = jsonObject . getJSONArray ( " data " ) ;
Boolean used = jsonObject . getBoolean ( " used " ) ;
@@ -226,8 +228,9 @@ public class SchBasePointServiceImpl extends ServiceImpl<SchBasePointMapper, Sch
return this . getOne ( lam ) ;
}
// 修复3: 修改方法添加synchronized
@Override
public void updateStatus ( JSONObject jsonObject ) {
public synchronized void updateStatus ( JSONObject jsonObject ) {
String device_code = jsonObject . getString ( " device_code " ) ;
Integer state = jsonObject . getInteger ( " state " ) ;
@@ -258,7 +261,7 @@ public class SchBasePointServiceImpl extends ServiceImpl<SchBasePointMapper, Sch
@Override
@Transactional ( rollbackFor = Exception . class )
public SchBasePoint selectByRegionCode ( String region_code , String vehicleCode , String piont_type ) {
synchronized ( lock2 ) {
synchronized ( SchBasePointServiceImpl . class ) {
//查询载具的类型
MdBaseVehicle mdBaseVehicle = iMdBaseVehicleService . selectByVehicleCode ( vehicleCode ) ;
if ( ObjectUtil . isEmpty ( mdBaseVehicle ) ) throw new BadRequestException ( " 载具类型不存在! " ) ;
@@ -279,14 +282,17 @@ public class SchBasePointServiceImpl extends ServiceImpl<SchBasePointMapper, Sch
* @return
*/
private SchBasePoint getSchBasePoint ( String regionCode , String pointType , MdBaseVehicle mdBaseVehicle ) {
synchronized ( SchBasePointServiceImpl . class ) {
List < SchBasePoint > 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<SchBasePointMapper, Sch
return schBasePoint ;
}
return null ;
}
}
@Override
@@ -306,6 +313,7 @@ public class SchBasePointServiceImpl extends ServiceImpl<SchBasePointMapper, Sch
@Override
public SchBasePoint selectByReassign ( String region_code , String vehicleCode ) {
synchronized ( SchBasePointServiceImpl . class ) {
//查询载具的类型
MdBaseVehicle mdBaseVehicle = iMdBaseVehicleService . getById ( vehicleCode ) ;
if ( ObjectUtil . isEmpty ( mdBaseVehicle ) ) throw new BadRequestException ( " 载具类型不存在! " ) ;
@@ -316,7 +324,9 @@ public class SchBasePointServiceImpl extends ServiceImpl<SchBasePointMapper, Sch
. eq ( SchBasePoint : : getRegion_code , region_code )
. 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 )
// 修复5: 添加行锁+LIMIT 1
. last ( " LIMIT 1 FOR UPDATE " ) ) ;
if ( CollUtil . isNotEmpty ( schBasePoints ) & & schBasePoints . size ( ) > 0 ) {
SchBasePoint schBasePoint1 = schBasePoints . get ( 0 ) ;
SchBasePoint schBasePoint = pointMapper . selectById ( schBasePoint1 . getNext_wait_point ( ) ) ;
@@ -334,7 +344,9 @@ public class SchBasePointServiceImpl extends ServiceImpl<SchBasePointMapper, Sch
. isNull ( SchBasePoint : : getVehicle_code )
. eq ( SchBasePoint : : getCan_vehicle_type , mdBaseVehicle . getVehicle_type ( ) )
. eq ( SchBasePoint : : getIs_used , true )
. eq ( SchBasePoint : : getPoint_status , GoodsEnum . OUT_OF_STOCK . getValue ( ) ) ) ;
. eq ( SchBasePoint : : getPoint_status , GoodsEnum . OUT_OF_STOCK . getValue ( ) )
// 修复6: 添加行锁+LIMIT 1
. last ( " LIMIT 1 FOR UPDATE " ) ) ;
if ( CollUtil . isNotEmpty ( schBasePoints1 ) & & schBasePoints1 . size ( ) > 0 ) {
SchBasePoint schBasePoint1 = schBasePoints1 . get ( 0 ) ;
SchBasePoint schBasePoint = pointMapper . selectById ( schBasePoint1 . getNext_wait_point ( ) ) ;
@@ -348,14 +360,18 @@ public class SchBasePointServiceImpl extends ServiceImpl<SchBasePointMapper, Sch
}
return null ;
}
}
@Override
public SchBasePoint selectByNextWaitPoint ( String device_code , String vehicleCode ) {
synchronized ( SchBasePointServiceImpl . class ) {
List < SchBasePoint > 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<SchBasePointMapper, Sch
}
return null ;
}
}
@Override
@Transactional ( rollbackFor = Exception . class )
public SchBasePoint selectByVehicleQty ( String vehicle_type ) {
synchronized ( SchBasePointServiceImpl . class ) {
Assert . noNullElements ( new Object [ ] { vehicle_type } , " 载具类型不能为空! " ) ;
List < SchBasePoint > 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<SchBasePointMapper, Sch
. eq ( " point_code " , schBasePoint . getPoint_code ( ) ) ) ;
return schBasePoint ;
}
}
@Override
public SchBasePoint selectByEmptyVehicleType ( String vehicle_type ) {
synchronized ( SchBasePointServiceImpl . class ) {
List < SchBasePoint > 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 < SchBasePoint > 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 < SchBasePoint > buildQueryWrapper ( String regionCode , String pointStatus , String vehicleType , int seq , int pointType , boolean includeRegionCode ) {
LambdaQueryWrapper < SchBasePoint > 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 < SchBasePoint > 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_typ e)
. eq ( StrUtil . isNotBlank ( vehicle_type ) , SchBasePoint : : getCan_vehicle_type , vehicle_type )
. isNull ( seq = = 2 , SchBasePoint : : getVehicles )
. isNull ( seq = = 1 , SchBasePoint : : getVehicle_code )
. eq ( Str Util. isNotBlank ( region_code ) , S chBasePoint: : getRegion_code , region_code )
. orderByAsc ( seq = = 2 , S chBasePoint : : getIn_order_seq ) ) ;
if ( CollUtil . isEmpty ( schBasePoints ) ) {
schBasePoints = pointMapper . selectList ( Wrappers . lambdaQuery ( S chBasePoint. class )
. eq ( S chBasePoint: : getIs_lock , false )
. eq ( S chBasePoint: : 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_cod e)
. orderByDesc ( SchBasePoint : : getIn_order_seq )
// 修复12: 添加行锁+LIMIT 1
. last ( " LIMIT 1 FOR UPDATE " ) ) ;
if ( Coll Util. isNotEmpty ( schBasePoints ) & & s chBasePoints . size ( ) > 0 ) {
SchBasePoint schBasePoint = s chBasePoints . get ( 0 ) ;
schBasePoint . setIs_lock ( true ) ;
PointUtils . setUpdateByAcs ( s chBasePoint) ;
updateById ( s chBasePoint) ;
return s chBasePoint;
}
return ( CollUtil . isNotEmpty ( schBasePoints ) & & schBasePoints . size ( ) > 0 ) ? s chBasePoints . get ( 0 ) : null ;
schBasePoints = pointMapper . selectList ( Wrappers . lambdaQuery ( S chBasePoint. 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 < String > 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 < 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 )
. 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 < String > 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<SchBasePointMapper, Sch
}
@Override
public SchBasePoint selectGroundByRegionCode ( String targetRegionCode , String value ) {
List < SchBasePoint > 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 < SchBasePoint > 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<SchBasePointMapper, Sch
@Override
public SchBasePoint selectPointByEmpAndRegion ( String region_code , String vehicle_code , String s ) {
synchronized ( lock4 ) {
synchronized ( SchBasePointServiceImpl . class ) {
//查询载具的类型
MdBaseVehicle mdBaseVehicle = iMdBaseVehicleService . getById ( vehicle_code ) ;
if ( ObjectUtil . isEmpty ( mdBaseVehicle ) ) throw new BadRequestException ( " 载具类型不存在! " ) ;
@@ -599,7 +717,9 @@ public class SchBasePointServiceImpl extends ServiceImpl<SchBasePointMapper, Sch
. eq ( SchBasePoint : : getPoint_type , s )
. eq ( SchBasePoint : : getRegion_code , region_code )
. eq ( SchBasePoint : : getPoint_status , GoodsEnum . OUT_OF_STOCK . getValue ( ) )
. eq ( SchBasePoint : : getIs_used , true ) ) ;
. eq ( SchBasePoint : : getIs_used , true )
// 修复15: 添加行锁+LIMIT 1
. last ( " LIMIT 1 FOR UPDATE " ) ) ;
if ( CollUtil . isNotEmpty ( schBasePoints ) & & schBasePoints . size ( ) > 0 ) {
SchBasePoint schBasePoint = schBasePoints . get ( 0 ) ;
schBasePoint . setIs_lock ( true ) ;
@@ -612,7 +732,9 @@ public class SchBasePointServiceImpl extends ServiceImpl<SchBasePointMapper, Sch
}
@Override
@Transactional
public SchBasePoint selectStackPoint ( String regionCode , String pointStatus , String vehicleType , int seq , int point_type ) {
synchronized ( SchBasePointServiceImpl . class ) {
List < SchBasePoint > 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<SchBasePointMapper, Sch
. eq ( SchBasePoint : : getRegion_code , regionCode )
. isNull ( seq = = 2 , SchBasePoint : : getVehicles )
. isNull ( seq = = 1 , SchBasePoint : : getVehicle_code )
. orderByAsc ( SchBasePoint : : getIn_order_seq ) ) ;
. orderByAsc ( SchBasePoint : : getIn_order_seq )
// 修复16: 添加行锁+LIMIT 1
. last ( " LIMIT 1 FOR UPDATE " ) ) ;
SchBasePoint schBasePoint = ( CollUtil . isNotEmpty ( schBasePoints ) & & schBasePoints . size ( ) > 0 ) ? schBasePoints . get ( 0 ) : null ;
if ( ObjectUtil . isNotEmpty ( schBasePoint ) ) {
schBasePoint . setIs_lock ( true ) ;
@@ -631,6 +755,7 @@ public class SchBasePointServiceImpl extends ServiceImpl<SchBasePointMapper, Sch
}
return schBasePoint ;
}
}
@Override
public List < OrderMater > getStructList ( String pointCode , String vehicle_type ) {
@@ -657,7 +782,7 @@ public class SchBasePointServiceImpl extends ServiceImpl<SchBasePointMapper, Sch
}
}
else {
structList = pointMapper . getStructList ( schBasePoint . getRegion_code ( ) , s ) ;
structList = pointMapper . getStructList ( schBasePoint . getRegion_code ( ) , s ) ;
}
List < OrderMater > collect = structList . stream ( ) . collect ( Collectors . groupingBy (
OrderMater : : getVehicle_code ,
@@ -679,34 +804,44 @@ public class SchBasePointServiceImpl extends ServiceImpl<SchBasePointMapper, Sch
return timestamp ;
}
// 修复17: 调整事务与锁顺序 - 外层锁,内部事务方法
@Override
@Transactional ( propagation = Propagation . REQUIRES_NEW )
public SchBasePoint selectEmpVehicleByRegionCode ( String region_code , String vehicleType ) {
synchronized ( lock3 ) {
//查询满足条件的站点
List < SchBasePoint > 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 < SchBasePoint > 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 ;
}
}