物流项目第四期(运费模板列表实现)
前三期:
物流项目第一期(登录业务)-CSDN博客
物流项目第二期(用户端登录与双token三验证)-CSDN博客
物流项目第三期(统一网关、工厂模式运用)-CSDN博客
模板列表
在后台系统中,需要对运费模板进行维护管理,所以首先需要查询列表:
Entity与Mapper
/*** 运费模板表*/
@Data
@EqualsAndHashCode(callSuper = false)
@AllArgsConstructor
@NoArgsConstructor
@TableName("sl_carriage")
public class CarriageEntity extends BaseEntity {private static final long serialVersionUID = -5358753714676282742L;/*** 模板类型:1-同城寄,2-省内寄,3-经济区互寄,4-跨省*/private Integer templateType;/*** 运送类型:1-普快,2-特快*/private Integer transportType;/*** 关联城市:1-全国,2-京津冀,3-江浙沪,4-川渝,5-黑吉辽*/private String associatedCity;/*** 首重价格*/private Double firstWeight;/*** 续重价格*/private Double continuousWeight;/*** 轻抛系数*/private Integer lightThrowingCoefficient;}
/*** 运费管理表 mapper接口*/
@Mapper
public interface CarriageMapper extends BaseMapper<CarriageEntity> {
}
Service
/*** 运费管理表 服务类*/
public interface CarriageService extends IService<CarriageEntity> {/*** 获取全部运费模板** @return 运费模板对象列表*/List<CarriageDTO> findAll();
}
@Slf4j
@Service
public class CarriageServiceImpl extends ServiceImpl<CarriageMapper, CarriageEntity> implements CarriageService {@Overridepublic List<CarriageDTO> findAll() {// 构造查询条件LambdaQueryWrapper<CarriageEntity> queryWrapper = Wrappers.<CarriageEntity>lambdaQuery()//按创建时间倒序.orderByDesc(CarriageEntity::getCreated);// 查询数据库List<CarriageEntity> list = super.list(queryWrapper);//转化对象,返回集合数据return CollStreamUtil.toList(list, carriageEntity -> {CarriageDTO carriageDTO = BeanUtil.toBean(carriageEntity, CarriageDTO.class);//关联城市数据按照逗号分割成集合carriageDTO.setAssociatedCityList(StrUtil.split(carriageEntity.getAssociatedCity(), ','));return carriageDTO;});}
}
Controller
@Slf4j
@Validated
@RestController
@Api(tags = "运费管理")
@RequestMapping("/carriages")
public class CarriageController {@Resourceprivate CarriageService carriageService;@GetMapping@ApiOperation(value = "运费模板列表")public List<CarriageDTO> findAll() {return this.carriageService.findAll();}}
代码优化
在查询模板列表时,返回数据时需要将Entity转化成DTO,像这样的转化是可以封装工具类来完成的,下面我们来封装com.sl.ms.carriage.utils.CarriageUtils
工具类。
/*** 运费模板工具类** 该工具类用于在 CarriageDTO(数据传输对象)与 CarriageEntity(实体对象)之间进行相互转换。* 主要处理运费模板中“关联城市”字段的格式转换:* - DTO 中使用 List<String> 存储多个城市名;* - Entity 中则以逗号分隔的字符串形式存储到数据库。*/
public class CarriageUtils {/*** 私有构造方法,防止外部实例化此类。** 因为这是一个纯工具类,不希望被 new 出来使用,所以将其构造方法私有化。*/private CarriageUtils() {// 不允许通过 new CarriageUtils() 创建对象}/*** 将 CarriageDTO 转换为 CarriageEntity。** @param carriageDTO 数据传输对象,包含运费模板相关信息* @return 返回对应的 CarriageEntity 实体对象,可用于保存到数据库*/public static CarriageEntity toEntity(CarriageDTO carriageDTO) {// 使用 Hutool 的 BeanUtil.toBean 方法将 DTO 对象属性复制到 Entity 对象中CarriageEntity carriage = BeanUtil.toBean(carriageDTO, CarriageEntity.class);// 将 DTO 中的 associatedCityList(城市列表,如 ["北京", "上海"])// 用 CollUtil.join 方法拼接成一个逗号分隔的字符串(如 "北京,上海")String associatedCity = CollUtil.join(carriageDTO.getAssociatedCityList(), ",");// 设置到 Entity 的 associatedCity 字段,以便存入数据库carriage.setAssociatedCity(associatedCity);// 返回转换后的 Entity 对象return carriage;}/*** 将 CarriageEntity 转换为 CarriageDTO。** @param carriage 数据库实体对象* @return 返回对应的 CarriageDTO 数据传输对象,用于返回给前端或业务层*/public static CarriageDTO toDTO(CarriageEntity carriage) {// 使用 Hutool 的 BeanUtil.toBean 方法将 Entity 对象属性复制到 DTO 对象中CarriageDTO carriageDTO = BeanUtil.toBean(carriage, CarriageDTO.class);// 从 Entity 的 associatedCity 字段(如 "北京,上海")中,// 使用 StrUtil.split 方法按逗号分割成 List<String>(如 ["北京", "上海"])List<String> associatedCityList = StrUtil.split(carriage.getAssociatedCity(), ',');// 设置到 DTO 的 associatedCityList 字段,便于后续使用或展示carriageDTO.setAssociatedCityList(associatedCityList);// 返回转换后的 DTO 对象return carriageDTO;}
}
@Slf4j
@Service
public class CarriageServiceImpl extends ServiceImpl<CarriageMapper, CarriageEntity> implements CarriageService {@Overridepublic List<CarriageDTO> findAll() {// 构造查询条件LambdaQueryWrapper<CarriageEntity> queryWrapper = Wrappers.<CarriageEntity>lambdaQuery()//按创建时间倒序.orderByDesc(CarriageEntity::getCreated);// 查询数据库List<CarriageEntity> list = super.list(queryWrapper);//转化对象,返回集合数据return CollStreamUtil.toList(list, CarriageUtils::toDTO);}
}
新增或更新运费模板
整体流程
Service
/*** 新增/修改运费模板** @param carriageDto 新增/修改运费对象* 必填字段:templateType、transportType* 更新时传入id字段*/CarriageDTO saveOrUpdate(CarriageDTO carriageDto);
@Overridepublic CarriageDTO saveOrUpdate(CarriageDTO carriageDto) {//1. 设置查询条件,查询运费模板列表LambdaQueryWrapper<CarriageEntity> queryWrapper = Wrappers.<CarriageEntity>lambdaQuery().eq(CarriageEntity::getTemplateType, carriageDto.getTemplateType()).eq(CarriageEntity::getTransportType, CarriageConstant.REGULAR_FAST);List<CarriageEntity> list = super.list(queryWrapper);//2. 判断是否为经济区互寄,如果不是,需要进一步的判断是否重复,如果是,需要判断关联城市是否重复if (ObjectUtil.notEqual(carriageDto.getTemplateType(), CarriageConstant.ECONOMIC_ZONE)) {if (CollUtil.isNotEmpty(list) && ObjectUtil.isEmpty(carriageDto.getId())) {//模板已经存在,数据重复throw new SLException(CarriageExceptionEnum.NOT_ECONOMIC_ZONE_REPEAT);}//更新时判断是否已经存在该类型的模板long count = StreamUtil.of(list).filter(carriageEntity -> ObjectUtil.notEqual(carriageEntity.getId(), carriageDto.getId())).count();if(count > 0){throw new SLException(CarriageExceptionEnum.NOT_ECONOMIC_ZONE_REPEAT);}//新增或更新return this.saveOrUpdateCarriage(carriageDto);}//3. 经济区互寄,校验关联城市是否有重复if (CollUtil.isEmpty(list)) {//直接新增或更新return this.saveOrUpdateCarriage(carriageDto);}//判断重复的思路:先将查询出的运费模板中的关联城市收集起来,传入的关联城市是否在此集合中//查询其他模板中所有的经济区列表List<String> associatedCityList = StreamUtil.of(list)//排除掉自己,检查与其他模板是否存在冲突.filter(carriageEntity -> ObjectUtil.notEqual(carriageEntity.getId(), carriageDto.getId()))//获取关联城市.map(CarriageEntity::getAssociatedCity)//将关联城市按照逗号分割.map(associatedCity -> StrUtil.split(associatedCity, ','))//将上面得到的集合展开,得到字符串.flatMap(StreamUtil::of)//收集到集合中.collect(Collectors.toList());//取交集,如果存在交集说明重复Collection<String> intersection = CollUtil.intersection(associatedCityList, carriageDto.getAssociatedCityList());if(CollUtil.isNotEmpty(intersection)){throw new SLException(CarriageExceptionEnum.ECONOMIC_ZONE_CITY_REPEAT);}//不重复return this.saveOrUpdateCarriage(carriageDto);}private CarriageDTO saveOrUpdateCarriage(CarriageDTO carriageDto) {CarriageEntity carriageEntity = CarriageUtils.toEntity(carriageDto);boolean result = super.saveOrUpdate(carriageEntity);if (result) {return CarriageUtils.toDTO(carriageEntity);}throw new SLException(CarriageExceptionEnum.SAVE_OR_UPDATE_ERROR);}
定义异常枚举:
/*** 异常枚举*/
public enum CarriageExceptionEnum implements BaseExceptionEnum {NOT_ECONOMIC_ZONE_REPEAT(1001, "非经济区的模板重复,只能有一个模板"),ECONOMIC_ZONE_CITY_REPEAT(1002, "经济区互寄关联城市重复"),NOT_FOUND(1003, "寄/收地址所属区域暂无计价规则,无法下单"),METHOD_CALL_ERROR(1004, "方法调用错误,经济区互寄不通过该方法查询模板"),SAVE_OR_UPDATE_ERROR(1005, "新增或更新运费模板失败");private Integer code;private Integer status;private String value;CarriageExceptionEnum(Integer code, String value) {this.code = code;this.value = value;this.status = 500;}CarriageExceptionEnum(Integer code, Integer status, String value) {this.code = code;this.value = value;this.status = status;}@Overridepublic Integer getCode() {return this.code;}@Overridepublic String getValue() {return this.value;}@Overridepublic Integer getStatus() {return this.status;}public static CarriageExceptionEnum codeOf(Integer code) {return EnumUtil.getBy(CarriageExceptionEnum::getCode, code);}
}
controller
@PostMapping@ApiOperation(value = "新增/修改运费模板")public CarriageDTO saveOrUpdate(@RequestBody CarriageDTO carriageDto) {return this.carriageService.saveOrUpdate(carriageDto);}