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

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 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 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 {

}

2)Service

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

public interface CategoryService extends IService {

/**

  • 根据父ID查询子分类

  • @param pid

  • @return

*/

List 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 queryByParentId(Integer pid) {

//条件封装

QueryWrapper queryWrapper = new QueryWrapper();

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> list(@PathVariable(value = “pid”)Integer pid){

List 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 queryBrandIds(Integer id);

2)Service

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

//根据分类ID查询品牌

List queryByCategoryId(Integer id);

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

/***

  • 根据分类ID查询品牌

  • @param id

  • @return

*/

@Override

public List queryByCategoryId(Integer id) {

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

List brandIds = brandMapper.queryBrandIds(id);

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

List brands = brandMapper.selectBatchIds(brandIds);

return brands;

}

3)Controller

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

/****

  • 根据分类ID查询品牌

*/

@GetMapping(value = “/category/{id}”)

public RespResult<List> categoryBrands(@PathVariable(value = “id”)Integer id){

List brands = brandService.queryByCategoryId(id);

return RespResult.ok(brands);

}

在这里插入图片描述

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 queryByCategoryId(Integer id);

2)Service

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

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

List queryList(Integer id);

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

/***

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

  • @param id

  • @return

*/

@Override

public List queryList(Integer id) {

return skuAttributeMapper.queryByCategoryId(id);

}

3)Controller

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

/***

  • 根据分类ID查询

*/

@GetMapping(value = “/category/{id}”)

public RespResult categoryAttributeList(@PathVariable(value = “id”)Integer id){

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

List 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 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 {

}

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

public interface SkuMapper extends BaseMapper {

}

Service

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

public interface SpuService extends IService {

//保存商品

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、其他流程和添加商品一致

修改com.bobo.vip.mall.goods.service.impl.SpuServiceImplsave方法,代码如下:

在这里插入图片描述

源码如下:

@Override

public void saveProduct(Product product) {

//Spu

Spu spu = product.getSpu();

//如果ID为空,则增加

if(StringUtils.isEmpty(spu.getId())){

//上架

spu.setIsMarketable(1);

//未删除

spu.setIsDelete(0);

//状态

spu.setStatus(1);

//添加

spuMapper.insert(spu);

}else{

//ID 不为空,则修改

spuMapper.updateById(spu);

//删除之前的Sku记录

skuMapper.delete(new QueryWrapper().eq(“spu_id”,spu.getId()));

}

//查询三级分类

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());

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

Java高频面试专题合集解析:

阿里Java岗面试百题:Spring 缓存 JVM 微服务 数据库 RabbitMQ等

当然在这还有更多整理总结的Java进阶学习笔记和面试题未展示,其中囊括了Dubbo、Redis、Netty、zookeeper、Spring cloud、分布式、高并发等架构资料和完整的Java架构学习进阶导图!

阿里Java岗面试百题:Spring 缓存 JVM 微服务 数据库 RabbitMQ等

更多Java架构进阶资料展示

阿里Java岗面试百题:Spring 缓存 JVM 微服务 数据库 RabbitMQ等

阿里Java岗面试百题:Spring 缓存 JVM 微服务 数据库 RabbitMQ等

阿里Java岗面试百题:Spring 缓存 JVM 微服务 数据库 RabbitMQ等
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
sku.setBrandId(brand.getId());

//设置品牌名称

sku.setBrandName(brand.getName());

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。[外链图片转存中…(img-yd6MKIN9-1713286702859)]

[外链图片转存中…(img-H4bS8OGf-1713286702859)]

[外链图片转存中…(img-5JQU9mAV-1713286702859)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

Java高频面试专题合集解析:

[外链图片转存中…(img-bVuyTuPc-1713286702860)]

当然在这还有更多整理总结的Java进阶学习笔记和面试题未展示,其中囊括了Dubbo、Redis、Netty、zookeeper、Spring cloud、分布式、高并发等架构资料和完整的Java架构学习进阶导图!

[外链图片转存中…(img-eibraHrD-1713286702860)]

更多Java架构进阶资料展示

[外链图片转存中…(img-ZbSSUTwr-1713286702860)]

[外链图片转存中…(img-JWcmvwxX-1713286702860)]

[外链图片转存中…(img-QG9PXKWk-1713286702860)]
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 20
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
购物商城的Spu-Sku数据库设计主要是为了管理商品的库存和销售信息。Spu(Standard Product Unit)是商品的标准产品单位,通常指的是一组具有相同特征但可能有不同规格的商品,例如同一款衣服的不同颜色或尺码。Sku(Stock Keeping Unit)是商品的库存管理单位,是对Spu的具体细分,用于区分不同规格或属性的商品。 在数据库设计中,可以建立两个主要的表:Spu表和Sku表。Spu表用于存储商品的基本信息,包括商品的名称、描述、品牌、分类等。此外,可以为Spu表添加一些扩展字段,例如商品的图片、销售状态等。 Sku表用于存储商品的具体规格和库存信息,其中包括Spu的外键关联、商品的属性、规格、价格和库存数量等。通过外键关联,可以将Sku与其对应的Spu关联起来,实现SpuSku的多对一关系。同时,可以在Sku表中添加一些扩展字段,例如商品的条形码、上架时间等。 为了提高查询效率,可以在Sku表中添加索引,例如根据商品的价格、库存数量、销售状态等字段进行索引,以快速获取满足条件的商品信息。 此外,为了提高系统的可维护性和可扩展性,可以添加一些辅助表,例如属性表和属性值表,用于管理商品的属性信息。属性表用于存储商品的属性名称,属性值表用于存储属性的具体取值范围。 总之,购物商城的Spu-Sku数据库设计需要考虑SpuSku之间的关联关系,以及商品的基本信息和规格信息的存储和管理。通过合理的设计和优化索引,可以提高系统的查询性能和用户体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值