物流项目第四期(运费模板列表实现)

前三期:

物流项目第一期(登录业务)-CSDN博客

物流项目第二期(用户端登录与双token三验证)-CSDN博客

物流项目第三期(统一网关、工厂模式运用)-CSDN博客

模板列表

在后台系统中,需要对运费模板进行维护管理,所以首先需要查询列表:

Entity与Mapper

java 复制代码
/**
 * 运费模板表
 */
@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;

}
java 复制代码
/**
 * 运费管理表 mapper接口
 */
@Mapper
public interface CarriageMapper extends BaseMapper<CarriageEntity> {
}
    

Service

java 复制代码
/**
 * 运费管理表 服务类
 */
public interface CarriageService extends IService<CarriageEntity> {

    /**
     * 获取全部运费模板
     *
     * @return 运费模板对象列表
     */
    List<CarriageDTO> findAll();
}
java 复制代码
@Slf4j
@Service
public class CarriageServiceImpl extends ServiceImpl<CarriageMapper, CarriageEntity> implements CarriageService {
    @Override
    public 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

java 复制代码
@Slf4j
@Validated
@RestController
@Api(tags = "运费管理")
@RequestMapping("/carriages")
public class CarriageController {

    @Resource
    private CarriageService carriageService;

    @GetMapping
    @ApiOperation(value = "运费模板列表")
    public List<CarriageDTO> findAll() {
        return this.carriageService.findAll();
    }

}

代码优化

在查询模板列表时,返回数据时需要将Entity转化成DTO,像这样的转化是可以封装工具类来完成的,下面我们来封装com.sl.ms.carriage.utils.CarriageUtils工具类。

java 复制代码
/**
 * 运费模板工具类
 *
 * 该工具类用于在 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;
    }
}
java 复制代码
@Slf4j
@Service
public class CarriageServiceImpl extends ServiceImpl<CarriageMapper, CarriageEntity> implements CarriageService {
    @Override
    public 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

java 复制代码
    /**
     * 新增/修改运费模板
     *
     * @param carriageDto 新增/修改运费对象
     *                    必填字段:templateType、transportType
     *                    更新时传入id字段
     */
    CarriageDTO saveOrUpdate(CarriageDTO carriageDto);
java 复制代码
    @Override
    public 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);
    }

定义异常枚举:

java 复制代码
/**
 * 异常枚举
 */
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;
    }

    @Override
    public Integer getCode() {
        return this.code;
    }

    @Override
    public String getValue() {
        return this.value;
    }

    @Override
    public Integer getStatus() {
        return this.status;
    }

    public static CarriageExceptionEnum codeOf(Integer code) {
        return EnumUtil.getBy(CarriageExceptionEnum::getCode, code);
    }
}

controller

java 复制代码
@PostMapping
    @ApiOperation(value = "新增/修改运费模板")
    public CarriageDTO saveOrUpdate(@RequestBody CarriageDTO carriageDto) {
        return this.carriageService.saveOrUpdate(carriageDto);
    }
相关推荐
程序猿小D22 分钟前
[附源码+数据库+毕业论文]基于Spring+MyBatis+MySQL+Maven+jsp实现的个人财务管理系统,推荐!
java·数据库·mysql·spring·毕业论文·ssm框架·个人财务管理系统
佛祖让我来巡山23 分钟前
【工厂和策略设计模式妙用】解决接口选择与多重if-else 问题
设计模式·策略模式·工厂模式
一禅(OneZen)1 小时前
「Windows/Mac OS」AIGC图片生成视频 ,webui + stable-diffusion环境部署教程
windows·stable diffusion
转转技术团队1 小时前
二奢仓店的静默打印代理实现
java·后端
wenzhangli71 小时前
从源码到思想:OneCode框架模块化设计如何解决前端大型应用痛点
架构·前端框架
钢铁男儿1 小时前
C# 接口(什么是接口)
java·数据库·c#
AirDroid_cn1 小时前
OPPO手机怎样被其他手机远程控制?两台OPPO手机如何相互远程控制?
android·windows·ios·智能手机·iphone·远程工作·远程控制
丶小鱼丶2 小时前
排序算法之【归并排序】
java·排序算法
上上迁2 小时前
分布式生成 ID 策略的演进和最佳实践,含springBoot 实现(Java版本)
java·spring boot·分布式
永日456702 小时前
学习日记-spring-day42-7.7
java·学习·spring