写点什么

2-2 SPU 和 SKU 详解及 MyBatisPlus 自动生成

作者:Java高工P7
  • 2021 年 11 月 10 日
  • 本文字数:5767 字

    阅读完需:约 19 分钟

2)选择品牌



分类选择完成后,需要加载品牌,品牌加载并非一次性加载完成,而是根据选择的分类进行加载。


分类品牌关系表:


CREATE TABLE category_brand (


category_id int(11) NOT NULL COMMENT '分类 ID',


brand_id int(11) NOT NULL COMMENT '品牌 ID',


PRIMARY KEY (brand_id,category_id)


) ENGINE=InnoDB DEFAULT CHARSET=utf8;


品牌表:


CREATE TABLE brand (


id int(11) NOT NULL AUTO_INCREMENT COMMENT '品牌 id',


name varchar(100) NOT NULL COMMENT '品牌名称',


image varchar(1000) DEFAULT '' COMMENT '品牌图片地址',


initial varchar(1) DEFAULT '' COMMENT '品牌的首字母',


sort int(11) DEFAULT NULL COMMENT '排序',


PRIMARY KEY (id)


) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8 COMMENT='品牌表';


3)属性加载



当选择分类后,加载分类对应的属性。


分类属性表:


CREATE TABLE category_attr (


category_id int(11) NOT NULL,


attr_id int(11) NOT NULL COMMENT '属性分类表',


PRIMARY KEY (category_id,attr_id)


) ENGINE=InnoDB DEFAULT CHARSET=utf8;


属性表:


CREATE TABLE sku_attribute (


id int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',


name varchar(50) DEFAULT NULL COMMENT '属性名称',


options varchar(2000) DEFAULT NULL COMMENT '属性选项',


sort int(11) DEFAULT NULL COMMENT '排序',


PRIMARY KEY (id)


) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8;


3、 商品发布加载功能




对应的 Bean 我们已经提前写好,如下


package com.bobo.vip.mall.goods.model;


import com.baomidou.mybatisplus.annotation.IdType;


import com.baomidou.mybatisplus.annotation.TableId;


import com.baomidou.mybatisplus.annotation.TableName;


import lombok.AllArgsConstructor;


import lombok.Data;


import lombok.NoArgsConstructor;


import java.io.Serializable;


/*****


  • @Author: 波波

  • @Description: 云商城


****/


@Data


@AllArgsConstructor


@NoArgsConstructor


//MyBatisPlus 表映射注解


@TableName(value = "category")


public class Category implements Serializable {


@TableId(type = IdType.AUTO)


private Integer id;


private String name;


private Integer sort;


private Integer parentId;


}


package com.bobo.vip.mall.goods.model;


import com.baomidou.mybatisplus.annotation.TableField;


import com.baomidou.mybatisplus.annotation.TableName;


import lombok.AllArgsConstructor;


import lombok.Data;


import lombok.NoArgsConstructor;


/*****


  • @Author: 波波

  • @Description: 云商城


****/


@Data


@AllArgsConstructor


@NoArgsConstructor


//MyBatisPlus 表映射注解


@TableName(value = "category_attr")


public class CategoryAttr {


@TableField


private Integer categoryId;


@TableField


private Integer attrId;


}


/*****


  • @Author: 波波

  • @Description: 云商城


****/


@Data


@AllArgsConstructor


@NoArgsConstructor


//MyBatisPlus 表映射注解


@TableName(value = "category_brand")


public class CategoryBrand {


@TableField


private Integer categoryId;


@TableField


private Integer brandId;


}


/*****


  • @Author: 波波

  • @Description: 云商城


****/


@Data


@NoArgsConstructor


@AllArgsConstructor


public class Product {


// Spu


private Spu spu;


// Sku


private List<Sku> skus;


}


@Data


@AllArgsConstructor


@NoArgsConstructor


//MyBatisPlus 表映射注解


@TableName(value = "sku")


public class Sku {


@TableId(type = IdType.ASSIGN_ID)


private String id;


private String name;


private Integer price;


private Integer num;


private String image;


private String images;


private Date createTime;


private Date updateTime;


private String spuId;


private Integer categoryId;


private String categoryName;


private Integer brandId;


private String brandName;


private String skuAttribute;


private Integer status;


}


/*****


  • @Author: 波波

  • @Description: 云商城


****/


@Data


@AllArgsConstructor


@NoArgsConstructor


//MyBatisPlus 表映射注解


@TableName(value = "sku_attribute")


public class SkuAttribute implements Serializable {


@TableId(type = IdType.AUTO)


private Integer id;


private String name;


private String options;


private Integer sort;


//对应分类


@TableField(exist = false)


private List<Category> categories;


}


@Data


@AllArgsConstructor


@NoArgsConstructor


//MyBatisPlus 表映射注解


@TableName(value = "spu")


public class Spu {


@TableId(type = IdType.ASSIGN_ID)


private String id;


private String name;


private String intro;


private Integer brandId;


private Integer categoryOneId;


private Integer categoryTwoId;


private Integer categoryThreeId;


private String images;


private String afterSalesService;


private String content;


private String attributeList;


private Integer isMarketable;


private Integer isDelete;


private Integer status;


}

3.1 分类加载

分类功能需要实现按照父 ID 查询,最开始初始化加载的是顶级父类,parent_id=0,后面每次点击的时候都根据传入的 id 查询子分类。


1)Mapper


创建com.bobo.vip.mall.goods.mapper.CategoryMapper,代码如下:


public interface CategoryMapper extends BaseMapper<Category> {


}


2)Service


接口:com.bobo.vip.mall.goods.service.CategoryService代码如下:


public interface CategoryService extends IService<Category> {


/**


  • 根据父 ID 查询子分类

  • @param pid

  • @return


*/


List<Category> queryByParentId(Integer pid);


}


实现类:com.bobo.vip.mall.goods.service.impl.CategoryServiceImpl代码如下:


@Service


public class CategoryServiceImpl extends ServiceImpl<CategoryMapper,Category> implements CategoryService {


@Autowired


private CategoryMapper categoryMapper;


/***


  • 根据父 ID 查询子分类

  • @param pid

  • @return


*/


@Override


public List<Category> queryByParentId(Integer pid) {


//条件封装


QueryWrapper<Category> queryWrapper = new QueryWrapper<Category>();


queryWrapper.eq("parent_id",pid);


return categoryMapper.selectList(queryWrapper);


}


}


3)Controller


创建com.bobo.vip.mall.goods.controller.CategoryController代码如下;


@RestController


@RequestMapping(value = "/category")


@CrossOrigin


public class CategoryController {


@Autowired


private CategoryService categoryService;


/****


  • 根据父 ID 查询子分类


*/


@GetMapping(value = "/parent/{pid}")


public RespResult<List<Category>> list(@PathVariable(value = "pid")Integer pid){


List<Category> categories = categoryService.queryByParentId(pid);


return RespResult.ok(categories);


}


}

3.2 品牌加载

品牌需要根据分类进行加载,当用户选择第 3 级分类的时候,加载品牌,品牌数据需要经过category_brand表关联查询。


我们可以按照如下步骤实现:


1、查询 category_brand 中指定分类对应的品牌 ID 集合


2、从 brand 查出品牌集合


1)Mapper


修改com.bobo.vip.mall.goods.mapper.BrandMapper,添加根据分类 ID 查询品牌 ID 集合:


//根据分类 ID 查询品牌集合


@Select("select brand_id from category_brand where category_id=#{id}")


List<Integer> queryBrandIds(Integer id);


2)Service


接口:com.bobo.vip.mall.goods.service.BrandService中添加根据分类 ID 查询品牌集合方法


//根据分类 ID 查询品牌


List<Brand> queryByCategoryId(Integer id);


实现类:com.bobo.vip.mall.goods.service.impl.BrandServiceImpl


/***


  • 根据分类 ID 查询品牌

  • @param id

  • @return


*/


@Override


public List<Brand> queryByCategoryId(Integer id) {


//查询分类 ID 对应的品牌集合


List<Integer> brandIds = brandMapper.queryBrandIds(id);


//根据品牌 ID 集合查询品牌信息


List<Brand> brands = brandMapper.selectBatchIds(brandIds);


return brands;


}


3)Controller


修改com.bobo.vip.mall.goods.controller.BrandController添加根据分类 ID 查询品牌集合


/****


  • 根据分类 ID 查询品牌


*/


@GetMapping(value = "/category/{id}")


public RespResult<List<Brand>> categoryBrands(@PathVariable(value = "id")Integer id){


List<Brand> brands = brandService.queryByCategoryId(id);


return RespResult.ok(brands);


}


![在这里插入图片描述](https://img-blog.csdnimg.cn/


【一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


20210115110726332.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NTI2NTcz,size_16,color_FFFFFF,t_70)

3.3 属性加载

属性也称为规格,属性也需要根据分类查询,我们可以按照如下思路实现:


1、先从 category_attr 根据分类 ID 查询出当前分类拥有的属性 ID 集合


2、从 sku_attribute 中查询属性集合


1)Mapper


创建com.bobo.vip.mall.goods.mapper.SkuAttributeMapper实现根据分类 ID 查询属性信息。


/***


  • 根据分类 ID 查询属性集合

  • @param id

  • @return


*/


@Select("SELECT * FROM sku_attribute WHERE id IN(SELECT attr_id FROM category_attr WHERE category_id=#{id})")


List<SkuAttribute> queryByCategoryId(Integer id);


2)Service


接口:com.bobo.vip.mall.goods.service.SkuAttributeService添加根据分类 ID 查询属性集合方法


//根据分类 ID 查询属性集合


List<SkuAttribute> queryList(Integer id);


实现类:com.bobo.vip.mall.goods.service.impl.SkuAttributeServiceImpl添加如下实现方法


/***


  • 根据分类 ID 查询属性集合

  • @param id

  • @return


*/


@Override


public List<SkuAttribute> queryList(Integer id) {


return skuAttributeMapper.queryByCategoryId(id);


}


3)Controller


创建com.bobo.vip.mall.goods.controller.SkuAttributeController,添加如下方法


/***


  • 根据分类 ID 查询


*/


@GetMapping(value = "/category/{id}")


public RespResult<SkuAttribute> categoryAttributeList(@PathVariable(value = "id")Integer id){


//根据分类 ID 查询属性参数


List<SkuAttribute> skuAttributes = skuAttributeService.queryList(id);


return RespResult.ok(skuAttributes);


}


4、商品发布



4.1 复合对象分析


商品发布,如上图,我们可以发现发布的商品信息包含 Sku 和 Spu,因此我们应该在后端能有一个对象同时能接到 Spu 和多个 Sku,方法有很多种,我们可以直接在 Spu 中写一个List<Sku>,但这种方法不推荐,按照对象设计原则,对一个对象进行扩展时,尽量避免对原始对象造成改变,因此我们可以使用复合类,可以创建一个Prodcut类,该类中有 Spu 也有List<Sku>,代码如下:


@Data


@NoArgsConstructor


@AllArgsConstructor


public class Product {


// Spu


private Spu spu;


// Sku


private List<Sku> skus;


}

4.2 添加商品

添加商品的时候,我们需要保存 Spu,同时需要添加多个 Sku。我们可以在华为商城中看看真实电商中 Sku 名字特征,每次点击不同属性的时候,前部分名字一样,只是将名字中的规格替换了,也就是说 Sku 的名字其实是组合成的,一部分是 Spu 的一部分是 Sku 的,可以进行组合。



1)名字分析


添加商品的时候,会将商品的属性传入后台,格式如下,如果把规格名字添加到名字中,那就是华为商城中的效果了,我们可以这么做,把属性解析成 Map,然后每个属性值添加到商品名字中即可。


{"适合人群":"有一定java基础的人","书籍分类":"软件编程"}


2)实现代码


Mapper


com.bobo.vip.mall.goods.mapper.SpuMapper代码如下:


public interface SpuMapper extends BaseMapper<Spu> {


}


com.bobo.vip.mall.goods.mapper.SkuMapper代码如下:


public interface SkuMapper extends BaseMapper<Sku> {


}


Service


com.bobo.vip.mall.goods.service.SpuService中添加产品方法如下


public interface SpuService extends IService<Spu> {


//保存商品


void saveProduct(Product product);


}


com.bobo.vip.mall.goods.service.impl.SpuServiceImpl中添加产品方法如下:


@Service


public class SpuServiceImpl extends ServiceImpl<SpuMapper,Spu> implements SpuService {


@Autowired


private SkuMapper skuMapper;


@Autowired


private SpuMapper spuMapper;


@Autowired


private CategoryMapper categoryMapper;


@Autowired


private BrandMapper brandMapper;


// 保存商品


@Override


public void saveProduct(Product product) {


//Spu


Spu spu = product.getSpu();


//上架


spu.setIsMarketable(1);


//未删除


spu.setIsDelete(0);


//状态


spu.setStatus(1);


//添加


spuMapper.insert(spu);


//查询三级分类


Category category = categoryMapper.selectById(spu.getCategoryThreeId());


//查询品牌


Brand brand = brandMapper.selectById(spu.getBrandId());


//当前时间


Date now = new Date();


//新增 Sku 集合


for (Sku sku : product.getSkus()) {


//设置名字


String skuName = spu.getName();


Map<String,String> attrMap = JSON.parseObject(sku.getSkuAttribute(), Map.class);


for (Map.Entry<String, String> entry : attrMap.entrySet()) {


skuName+= " "+entry.getValue();


}


sku.setName(skuName);


//设置图片


sku.setImages(spu.getImages());


//设置状态


sku.setStatus(1);


//设置类目 ID


sku.setCategoryId(spu.getCategoryThreeId());


//设置类目名称


sku.setCategoryName(category.getName());


//设置品牌 ID


sku.setBrandId(brand.getId());


//设置品牌名称


sku.setBrandName(brand.getName());


//设置 Spuid


sku.setSpuId(spu.getId());


//时间


sku.setCreateTime(now);


sku.setUpdateTime(now);


//增加


skuMapper.insert(sku);


}


}


}


Controller


创建com.bobo.vip.mall.goods.controller.SpuController,添加产品代码如下:


@Autowired


private SpuService spuService;


/***


  • 保存


*/


@PostMapping(value = "/save")


public RespResult save(@RequestBody Product product){


//保存


spuService.saveProduct(product);


return RespResult.ok();


}

4.3 产品修改

产品修改其实和产品添加几乎一致,只需要做小改动即可,实现步骤如下:


1、如果 Spu 的 id 值不为空,说明是修改操作


2、如果是修改操作,先删除之前对应的 Sku 集合


3、其他流程和添加商品一致

用户头像

Java高工P7

关注

还未添加个人签名 2021.11.08 加入

还未添加个人简介

评论

发布
暂无评论
2-2 SPU和SKU详解及MyBatisPlus自动生成