前三期:
物流项目第二期(用户端登录与双token三验证)-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);
}