前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >猿实战21——商品发布之商品数据存储

猿实战21——商品发布之商品数据存储

作者头像
山旮旯的胖子
发布2020-10-22 11:10:35
5540
发布2020-10-22 11:10:35
举报
文章被收录于专栏:猿人工厂

猿实战是一个原创系列文章,通过实战的方式,采用前后端分离的技术结合SpringMVC Spring Mybatis,手把手教你撸一个完整的电商系统,变身猿人找到工作不是问题。还等什么呢?关注公号,取基础代码,一起实战吧。

上个章节,猿人君教会了你如何生成sku数据,你还学到了一个新的算法——笛卡尔乘积的相关运算。

今天猿人君继续带你来实现商品发布的核心功能——商品数据的保存。

功能概览

在商品发布详情页面,填写完商品的相关信息后,点击保存按钮,记录商品相关信息,并将这些商品信息记录为仓库中的状态。

数据库设计

根据之前的设计相关文章,我们整理得出商品信息的数据库物理信息如下。

商品主表

商品扩展表

商品图片表

商品销售属性表

SKU表

SKU图片表

VO设计

描述商品的完整信息,实际上是一个数据聚合的过程。简单点来讲,商品除了需要描述自身的一些基本特性(名称,描述,包装信息等等)外,一些其他的特征,比如商品属性、比如图片、比如sku等等,都需要通过一个良好的数据结构描述出来。我们看下图:

对于1:1的关系,我们将其定义为属性即可,对于1:N的关系,我们可以使用List来表达含义。于是我们很可以较为容易的得出用于传递商品信息的VO.

代码语言:javascript
复制
public class ProductVo extends BaseDO {
 
    /**商品ID**/
    private Long productId;
 
    /**商品名称**/
    private String productName;
 
    /**商家ID**/
    private Long sellerId;
 
    /**商家名称**/
    private String sellerName;
 
    /**一级类目ID**/
    private Long categoryOneId;
 
    /**一级类目名称**/
    private String categoryOneName;
 
    /**二级类目ID**/
    private Long categoryTwoId;
 
    /**二级类目名称**/
    private String categoryTwoName;
 
    /**三级类目ID**/
    private Long categoryThreeId;
 
    /**三级类目名称**/
    private String categoryThreeName;
 
    /**预留商品编码**/
    private String productCode;
 
    /**预留商家商品编码**/
    private String sellerProductCode;
 
    /**是否预售**/
    private Integer preSale;
 
    /**供货价**/
    private BigDecimal supplyPrice;
 
    /**成本价**/
    private BigDecimal costPrice;
 
    /**品牌ID**/
    private Long brandId;
 
    /**品牌名称**/
    private String brandName;
 
    /**
     * 商品属性
     */
    private List<MallCategoryPropertyVo> propertites;
 
 
 
    /**预留扩展**/
    private String features;
 
    /**商品描述**/
    private String productDesc;
 
    /**商品主图**/
    private String imgUrl;
 
    /**商品图片**/
    private List<String> imgList;
 
    /**商品主skuId**/
    private Long mainSkuId;
 
    /**运费模板ID**/
    private Long freightTempleteId;
 
    /**发货时长**/
    private Integer deliveryHours;
 
    /**1下架2上架-1删除**/
    private Integer status;
 
    /**毛重**/
    private BigDecimal grossWeight;
 
    /**净重**/
    private BigDecimal netWeight;
 
    /**长**/
    private BigDecimal length;
 
    /**宽**/
    private BigDecimal width;
 
    /**高**/
    private BigDecimal height;
 
    /**包装长**/
    private BigDecimal packLength;
 
    /**包装宽**/
    private BigDecimal packWidth;
 
    /**包装高**/
    private BigDecimal packHeight;
 
    /**包装清单**/
    private String packageInfo;
    /**
     * 商品属性
     */
    private List<MallCategoryPropertyVo> salePropertites;
 
 
    /**
     * sku列表
     */
    private List<SkuVo> skuList;
}
代码语言:javascript
复制
public class SkuVo extends BaseDO {
 
    /**
     * sku Id
     */
    private Long id;
 
    private Long skuId;
 
    private String skuName;
    // 供货价
    private BigDecimal supplyPrice;
    // 卖家SKU编码
    private String skuCode;
    // 成本价
    private BigDecimal costPrice;
 
    //展示的销售属性名称
    private String proValueName;
 
    private List<String> imgList = new ArrayList<String>();
 
    private List<PropertyValueVo>  proValues = new  ArrayList<PropertyValueVo>();
}
 
public class PropertyValueVo extends BaseDO {
 
    /**
     * 属性ID
     */
    private Long  propertyId;
 
    /**
     * 属性值ID
     */
    private Long  propertyValueId;
}

VO数据持久化

我们将需要持久化的数据,通过VO的形式封装起来,这部分数据和我们最终要用于持久的Domain是有一些差距的。那么持久数据之前,你需要做一些准备。

大致可以分为以下几个步骤:

1. 构建商品主数据

代码语言:javascript
复制
private MallProduct buildMallProduct(ProductVo product){
MallProduct mallProduct = new MallProduct();
BeanUtils.copyProperties(product,mallProduct);
List<PropertyValueVo> dataList =
buildCheckedPropertyList(product.getPropertites(),product.getProCheckedList());
List<PropertyValueVo> proList =
buildCheckedPropertyList(product.getPropertites(),product.getProCheckedList());
Set<Long> proIdList=proList.stream().map(e -> e.getPropertyId()).collect(Collectors.toSet());
List<Long> propertyIdList= new ArrayList<Long>();
propertyIdList.addAll(proIdList);
mallProduct.setProperties(JSON.toJSONString(proIdList));
mallProduct.setPropertityValues(JSON.toJSONString(dataList));
mallProduct.setStatus(ProductStatusEnum.STATUS_IN_HOURSE.getStatusValue());
    return  mallProduct;
 
}
 
private List<PropertyValueVo> buildCheckedPropertyList
(List<MallCategoryPropertyVo> propertyList,List<Long> checkedList) {
List<PropertyValueVo> dataList = new ArrayList<PropertyValueVo>();
for(MallCategoryPropertyVo vo:propertyList){
 
for(MallCategoryPropertyValueVo valueVo:vo.getValueList()){
for(Long valueId:checkedList) {
if (valueId.longValue() == valueVo.getId().longValue()) {
 
PropertyValueVo dataVo = new PropertyValueVo();
dataVo.setPropertyId(vo.getId());
dataVo.setPropertyValueId(valueId);
dataList.add(dataVo);
}
}
}
 
}
return dataList;
}

注意,文中为了实现方便,使用了BeanUtils来处理数据,但是实际的场景中,前后端的字段名往往是不一样的,你用了也没啥大用,也不推荐你使用这种方式来处理。一个一个字段去匹配书写是你的职责,同时也能加深你对业务的把握,同时也是对代码负责的一种态度。

2. 构建商品扩展数据

代码语言:javascript
复制
private MallProductExt buildProductExt(ProductVo product ,Long productId){
MallProductExt productExt = new MallProductExt();
BeanUtils.copyProperties(product,productExt);
productExt.setStatus(DataActiveStatusEnum.STATUS_ACTIVE.getStatusValue());
productExt.setProductId(productId);
return  productExt;
}

3. 构建商品图片数据

代码语言:javascript
复制
private List<MallProductImg> buildProductImgList(ProductVo product,Long productId){
 
    List<MallProductImg> dataList = new ArrayList<MallProductImg>();
    for(String imgUrl:product.getImgList()){
MallProductImg mallProductImg = new MallProductImg();
BeanUtils.copyProperties(product,mallProductImg);
mallProductImg.setProductImgUrl(imgUrl);
mallProductImg.setProductId(productId);
mallProductImg.setStatus(DataActiveStatusEnum.STATUS_ACTIVE.getStatusValue());
dataList.add(mallProductImg);
}
 
return  dataList;
}

4. 构建商品销售属性数据

代码语言:javascript
复制
private MallProductSaleProperty buildProductSaleProperty(ProductVo product,Long productId){
MallProductSaleProperty saleProperty = new MallProductSaleProperty();
BeanUtils.copyProperties(product,saleProperty);
saleProperty.setProductId(productId);
saleProperty.setStatus(DataActiveStatusEnum.STATUS_ACTIVE.getStatusValue());
List<PropertyValueVo> dataList =
buildCheckedPropertyList(product.getSalePropertites(),product.getSaleCheckedList());
 
Set<Long> proIdList=dataList.stream().map(e -> e.getPropertyId()).collect(Collectors.toSet());
 
List<Long> propertyIdList= new ArrayList<Long>();
propertyIdList.addAll(proIdList);
//设置属性
saleProperty.setSaleProperties(JSON.toJSONString(propertyIdList));
//设置属性值
saleProperty.setSalePropertyValues(JSON.toJSONString(dataList));
 
return  saleProperty;
}
 

5. 构建sku数据

代码语言:javascript
复制
private List<MallProductSku> buildMallSkuList(ProductVo product,MallProduct mallProduct){
List<MallProductSku> dataList = new ArrayList<MallProductSku>();
    for(SkuVo skuVo:product.getSkuList()){
MallProductSku sku = new MallProductSku();
BeanUtils.copyProperties(product,sku);
//注意不要随意交换位置,要不价格信息会被覆盖掉
BeanUtils.copyProperties(skuVo,sku);
sku.setProductId(mallProduct.getProductId());
//sku.setSalePropertityValues(skuVo);
Set<Long> proIdList=skuVo.getProValues().stream().map(e -> e.getPropertyId()).collect(Collectors.toSet());
List<Long> propertyIdList= new ArrayList<Long>();
propertyIdList.addAll(proIdList);
 
//属性和属性值继承父类
sku.setProperties(mallProduct.getProperties());
sku.setPropertityValues(mallProduct.getPropertityValues());
 
//销售属性销售属性值
sku.setSaleProperties(JSON.toJSONString(proIdList));
sku.setSalePropertityValues(JSON.toJSONString(skuVo.getProValues()));
 
List<MallProductSkuImg> imgList= buildMallSkuImgList(product,skuVo,mallProduct.getProductId());
sku.setImgList(imgList);
            dataList.add(sku);
}
 
return  dataList;
}

6. 构建sku图片数据

代码语言:javascript
复制
private List<MallProductSkuImg> buildMallSkuImgList(ProductVo product,SkuVo skuVo, Long productId){
List<MallProductSkuImg> dataList = new ArrayList<MallProductSkuImg>();
for(String imgUrl:skuVo.getImgList()){
MallProductSkuImg skuImg = new MallProductSkuImg();
BeanUtils.copyProperties(product,skuImg);
BeanUtils.copyProperties(skuVo,skuImg);
skuImg.setProductId(productId);
skuImg.setStatus(DataActiveStatusEnum.STATUS_ACTIVE.getStatusValue());
skuImg.setId(null);
dataList.add(skuImg);
}
return  dataList;
}

最后,我们来聊一聊数据持久的具体细节。商品的数据是有关联性的,商品扩展、商品图片、商品销售属性、sku、sku图片其实都依赖于商品主数据ID的,而sku图片,还依赖于skuId的数据。所以在持久数据的时候,大概会是这样一个顺序:商品->商品扩展->商品图片->商品销售属性->商品->sku->sku图片。

考虑到你目前的学习进度和基础,在数据持久层面,猿人君并没有采取特别的处理,让你先熟悉熟悉基本的操作,后续的一些文中,可能会出现批量处理的优化方式。

代码语言:javascript
复制
   public Result<ProductVo> addMallProduct(ProductVo product) {
Result<ProductVo> result = new Result<ProductVo>();
try {
MallProduct mallProduct=buildMallProduct(product);
mallProductDao.insertMallProductModified(mallProduct);
product.setProductId(mallProduct.getProductId());
MallProductExt mallProductExt=buildProductExt(product,mallProduct.getProductId());
mallProductExtDao.insertMallProductExtModified(mallProductExt);
 
List<MallProductImg> productImgList =
buildProductImgList(product,mallProduct.getProductId());
for(MallProductImg img:productImgList){
mallProductImgDao.insertMallProductImgModified(img);
}
 
MallProductSaleProperty saleProperty=buildProductSaleProperty(product,mallProduct.getProductId());
mallProductSalePropertyDao.insertMallProductSalePropertyModified(saleProperty);
 
List<MallProductSku> skuList =
buildMallSkuList(product,mallProduct);
for(MallProductSku sku:skuList){
mallProductSkuDao.insertMallProductSku(sku);
for(MallProductSkuImg img:sku.getImgList()){
img.setSkuId(sku.getSkuId());
mallProductSkuImgDao.insertMallProductSkuImgModified(img);
}
}
 
} catch(Exception e) {
result.setSuccess(false);
}
result.addDefaultModel(product);
return result;
    }
 
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-10-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 猿人工厂 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档