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.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.SpuServiceImpl
的save
方法,代码如下:
在这里插入图片描述
源码如下:
@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开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Java开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
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-myjj5GXw-1715590769362)]
[外链图片转存中…(img-O3LO0oo8-1715590769363)]
[外链图片转存中…(img-H5rjmZAK-1715590769363)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Java开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!