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

前三期:

物流项目第一期(登录业务)-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);
    }
相关推荐
hackchen10 分钟前
NexusTerminal一款视频移动端的webSSH
docker·云原生·eureka·web-ssh
木棉软糖35 分钟前
【记录坑点问题】IDEA运行:maven-resources-production:XX: OOM: Java heap space
java·maven·intellij-idea
chusheng18401 小时前
2025最新版!Windows Python3 超详细安装图文教程(支持 Python3 全版本)
windows·python·python3下载·python 安装教程·python3 安装教程
山猪打不过家猪1 小时前
(三)总结(缓存/ETag请求头)
缓存·微服务
自由鬼1 小时前
企业架构框架深入解析:TOGAF、Zachman Framework、FEAF与Gartner EA Framework
程序人生·架构
jiedaodezhuti1 小时前
EFK架构的数据安全性
架构
秋田君1 小时前
深入理解JavaScript设计模式之策略模式
javascript·设计模式·策略模式
海天鹰2 小时前
C盘瘦身?
windows
Java知识库2 小时前
2025秋招后端突围:JVM核心面试题与高频考点深度解析
java·jvm·程序员·java面试·后端开发
南枝异客2 小时前
四数之和-力扣
java·算法·leetcode