商城
SPU与SKU概念
SPU = Standard Product Unit (标准产品单位)
-
概念 : SPU 是商品信息聚合的最小单位,是一组可复用、易检索的标准化信息的集合,该集合描述了一个产品的特性。
-
通俗点讲,属性值、特性相同的货品就可以称为一个 SPU
==同款商品的公共属性抽取==
例如:**华为P30 就是一个 SPU**
SKU=stock keeping unit( 库存量单位)
-
SKU 即库存进出计量的单位, 可以是以件、盒、托盘等为单位。
-
SKU 是物理上不可分割的最小存货单元。在使用时要根据不同业态,不同管理模式来处理。
-
在服装、鞋类商品中使用最多最普遍。
例如:**华为P30 红色 64G 就是一个 SKU**
==某个库存单位的商品独有属性(某个商品的独有属性)==
举例:
优点:更节省空间
表结构分析
tb_spu 表 (SPU表)
字段名称 | 字段含义 | 字段类型 | 字段长度 | 备注 |
---|---|---|---|---|
id | 主键 | BIGINT | ||
sn | 货号 | VARCHAR | ||
name | SPU名 | VARCHAR | ||
caption | 副标题 | VARCHAR | ||
brand_id | 品牌ID | INT | ||
category1_id | 一级分类 | INT | ||
category2_id | 二级分类 | INT | ||
category3_id | 三级分类 | INT | ||
template_id | 模板ID | INT | ||
freight_id | 运费模板id | INT | ||
image | 图片 | VARCHAR | ||
images | 图片列表 | VARCHAR | ||
sale_service | 售后服务 | VARCHAR | ||
introduction | 介绍 | TEXT | ||
spec_items | 规格列表 | VARCHAR | ||
para_items | 参数列表 | VARCHAR | ||
sale_num | 销量 | INT | ||
comment_num | 评论数 | INT | ||
is_marketable | 是否上架 | CHAR | ||
is_enable_spec | 是否启用规格 | CHAR | ||
is_delete | 是否删除 | CHAR | ||
status | 审核状态 | CHAR |
tb_sku 表(SKU商品表)
字段名称 | 字段含义 | 字段类型 | 字段长度 | 备注 |
---|---|---|---|---|
id | 商品id | BIGINT | ||
sn | 商品条码 | VARCHAR | ||
name | SKU名称 | VARCHAR | ||
price | 价格(分) | INT | ||
num | 库存数量 | INT | ||
alert_num | 库存预警数量 | INT | ||
image | 商品图片 | VARCHAR | ||
images | 商品图片列表 | VARCHAR | ||
weight | 重量(克) | INT | ||
create_time | 创建时间 | DATETIME | ||
update_time | 更新时间 | DATETIME | ||
spu_id | SPUID | BIGINT | ||
category_id | 类目ID | INT | ||
category_name | 类目名称 | VARCHAR | ||
brand_name | 品牌名称 | VARCHAR | ||
spec | 规格 | VARCHAR | ||
sale_num | 销量 | INT | ||
comment_num | 评论数 | INT | ||
status | 商品状态 1-正常,2-下架,3-删除 | CHAR |
商品添加-分类查询实现流程分析
品牌查询实现方案分析
商品添加-规格查询分析
商品添加-参数查询实现
代码生成器使用
将代码生成器code-template拷贝进去:
打开idea,即可看到
添加到maven仓库:
可以看到:
修改代码生成器的配置:
右键Run运行即可:
我反复测试了下,视频自带的资料,和我在网上找的源码中的的代码生成器都不行
还是在官方提供的地址下吧:.git
下载好解压,操作和上面一样:
测试可以生成,哈哈,测试了好久,终于成功了,有点小成就感。
红叉说明没有jar包,不用担心,直接拷贝过去就好了
只要包的路径一致就ok啦:
package com.changgou.goods
一会儿会用到ID生成,我们可以使用IdWorker,在启动类GoodsApplication中添加如下代码,用于创建IdWorker,并将IdWorker交给Spring容器,代码如下:
/**** IdWorker* @return*/
@Bean
public IdWorker idWorker(){return new IdWorker(0,0);
}
工具类在common中:
查询分类:
在实现商品增加之前,需要先选择对应的分类,选择分类的时候,首选选择一级分类,然后根据选中的分类,将选中的分类作为查询的父ID,
再查询对应的子分类集合,因此我们可以在后台编写一个方法,根据父类ID查询对应的分类集合即可。
修改com.changgou.goods.service.CategoryService
添加根据父类ID查询所有子节点,代码如下:
/**** 根据分类的父ID查询子分类节点集合*/
List<Category> findByParentId(Integer pid);
修改com.changgou.goods.service.impl.CategoryServiceImpl
添加上面的实现,代码如下:
/**** 根据分类的父节点ID查询所有子节点* @param pid* @return*/
@Override
public List<Category> findByParentId(Integer pid) {//SELECT * FROM tb_category WHERE parent_id=?Category category = new Category();category.setParentId(pid);return categoryMapper.select(category);
}
修改com.changgou.goods.controller.CategoryController
添加根据父ID查询所有子类集合,代码如下:
/***** 根据节点ID查询所有子节点分类集合*/
@GetMapping(value = "/list/{pid}")
public Result<List<Category>> findByParentId(@PathVariable(value = "pid")Integer pid){//调用Service实现查询List<Category> categories = categoryService.findByParentId(pid);return new Result<List<Category>>(true,StatusCode.OK,"查询成功!",categories);
}
模板查询(规格参数组):
/**** 根据分类查询模板数据* @param id:分类ID*/
@GetMapping(value = "/category/{id}")
public Result<Template> findByCategoryId(@PathVariable(value = "id")Integer id){//调用Service查询Template template = templateService.findByCategoryId(id);return new Result<Template>(true, StatusCode.OK,"查询成功",template);
}/*** 根据分类ID查询模板信息* @param id* @return*/
Template findByCategoryId(Integer id);@Autowired
private CategoryMapper categoryMapper;/**** 根据分类ID查询模板信息* @param id* @return*/
@Override
public Template findByCategoryId(Integer id) {//查询分类信息Category category = categoryMapper.selectByPrimaryKey(id);//根据模板Id查询模板信息return templateMapper.selectByPrimaryKey(category.getTemplateId());
}
查询分类品牌数据:
用户每次选择了分类之后,可以根据用户选择的分类到tb_category_brand
表中查询指定的品牌集合ID,
然后根据品牌集合ID查询对应的品牌集合数据,再将品牌集合数据拿到这里来展示即可实现上述功能。
/**** 根据分类实现品牌列表查询* /brand/category/{id} 分类ID*/
@GetMapping(value = "/category/{id}")
public Result<List<Brand>> findBrandByCategory(@PathVariable(value = "id")Integer categoryId){//调用Service查询品牌数据List<Brand> categoryList = brandService.findByCategory(categoryId);return new Result<List<Brand>>(true,StatusCode.OK,"查询成功!",categoryList);
}/**** 根据分类ID查询品牌集合* @param categoryid:分类ID*/
List<Brand> findByCategory(Integer categoryid);/**** 根据分类ID查询品牌集合* @param categoryid:分类ID* @return*/
@Override
public List<Brand> findByCategory(Integer categoryid) {//1.查询当前分类所对应的所有品牌信息//2.根据品牌ID查询对应的品牌集合//自己创建DAO实现查询return brandMapper.findByCategory(categoryid);
}/**** 查询分类对应的品牌集合*/
@Select("SELECT tb.* FROM tb_category_brand tcb,tb_brand tb WHERE tcb.category_id=#{categoryid} AND tb.id=tcb.brand_id")
List<Brand> findByCategory(Integer categoryid);
规格查询:
/**** 根据分类ID查询对应的规格列表*/
@GetMapping(value = "/category/{id}")
public Result<List<Spec>> findByCategoryId(@PathVariable(value = "id")Integer categoryid){//调用Service查询List<Spec> specs = specService.findByCategoryId(categoryid);return new Result<List<Spec>>(true, StatusCode.OK,"查询成功",specs);
}/**** 根据分类ID查询规格列表* @param categoryid* @return*/
List<Spec> findByCategoryId(Integer categoryid);@Autowired
private CategoryMapper categoryMapper;/**** 根据分类ID查询规格列表* @param categoryid* @return*/
@Override
public List<Spec> findByCategoryId(Integer categoryid) {//查询分类Category category = categoryMapper.selectByPrimaryKey(categoryid);//根据分类的模板ID查询规格Spec spec = new Spec();spec.setTemplateId(category.getTemplateId());return specMapper.select(spec);
}
参数列表查询:
/*** 根据分类ID查询参数列表* @param id* @return*/
@GetMapping(value = "/category/{id}")
public Result<List<Para>> getByCategoryId(@PathVariable(value = "id")Integer id){//根据分类ID查询对应的参数信息List<Para> paras = paraService.findByCategoryId(id);Result<List<Para>> result = new Result<List<Para>>(true,StatusCode.OK,"查询分类对应的品牌成功!",paras);return result;
}/**** 根据分类ID查询参数列表* @param id* @return*/
List<Para> findByCategoryId(Integer id);@Autowired
private CategoryMapper categoryMapper;/**** 根据分类ID查询参数列表* @param id* @return*/
@Override
public List<Para> findByCategoryId(Integer id) {//查询分类信息Category category = categoryMapper.selectByPrimaryKey(id);//根据分类的模板ID查询参数列表Para para = new Para();para.setTemplateId(category.getTemplateId());return paraMapper.select(para);
}
测试上面的接口:
注册中心:http://localhost:7001/
http://localhost:18081/category/list/0
{"flag": true,"code": 20000,"message": "查询成功!","data": [{"id": 1,"name": "图书、音像、电子书刊","goodsNum": 100,"isShow": "0","isMenu": "0","seq": 1,"parentId": 0,"templateId": 42},{"id": 74,"name": "家用电器","goodsNum": 100,"isShow": "1","isMenu": "0","seq": 1,"parentId": 0,"templateId": 42},{"id": 161,"name": "电脑、办公","goodsNum": 100,"isShow": "1","isMenu": "0","seq": 1,"parentId": 0,"templateId": 42},{"id": 249,"name": "个护化妆","goodsNum": 100,"isShow": "1","isMenu": "0","seq": 1,"parentId": 0,"templateId": 42},{"id": 290,"name": "钟表","goodsNum": 100,"isShow": "1","isMenu": "0","seq": 1,"parentId": 0,"templateId": 42},{"id": 296,"name": "母婴","goodsNum": 100,"isShow": "1","isMenu": "0","seq": 1,"parentId": 0,"templateId": 42},{"id": 378,"name": "食品饮料、保健食品","goodsNum": 100,"isShow": "1","isMenu": "0","seq": 1,"parentId": 0,"templateId": 42},{"id": 438,"name": "汽车用品","goodsNum": 100,"isShow": "1","isMenu": "0","seq": 1,"parentId": 0,"templateId": 42},{"id": 495,"name": "玩具乐器","goodsNum": 100,"isShow": "0","isMenu": "0","seq": 1,"parentId": 0,"templateId": 42},{"id": 558,"name": "手机","goodsNum": 100,"isShow": "1","isMenu": "0","seq": 1,"parentId": 0,"templateId": 42},{"id": 580,"name": "数码","goodsNum": 100,"isShow": "1","isMenu": "0","seq": 1,"parentId": 0,"templateId": 43},{"id": 633,"name": "家居家装","goodsNum": 100,"isShow": "1","isMenu": "0","seq": 1,"parentId": 0,"templateId": 42},{"id": 699,"name": "厨具","goodsNum": 100,"isShow": "1","isMenu": "0","seq": 1,"parentId": 0,"templateId": 42},{"id": 749,"name": "服饰内衣","goodsNum": 100,"isShow": "1","isMenu": "0","seq": 1,"parentId": 0,"templateId": 42},{"id": 865,"name": "鞋靴","goodsNum": 100,"isShow": "1","isMenu": "0","seq": 1,"parentId": 0,"templateId": 42},{"id": 903,"name": "礼品箱包","goodsNum": 100,"isShow": "1","isMenu": "0","seq": 1,"parentId": 0,"templateId": 42},{"id": 963,"name": "珠宝","goodsNum": 100,"isShow": "0","isMenu": "0","seq": 1,"parentId": 0,"templateId": 42},{"id": 1031,"name": "运动健康","goodsNum": 100,"isShow": "1","isMenu": "0","seq": 1,"parentId": 0,"templateId": 42},{"id": 1147,"name": "彩票、旅行、充值、票务","goodsNum": 100,"isShow": "0","isMenu": "0","seq": 1,"parentId": 0,"templateId": 42}]
}
http://localhost:18081/brand/category/11156
{"flag": true,"code": 20000,"message": "查询成功!","data": [{"id": 18374,"name": "小米","image": ".jpg","letter": "X","seq": null},{"id": 325414,"name": "手机配件","image": "","letter": "S","seq": null}]
}
http://localhost:18081/spec/category/11156
{"flag": true,"code": 20000,"message": "查询成功","data": [{"id": 27,"name": "网络","options": "联通2G,联通3G,联通4G,移动4G,联通3G/移动4G,电信4G","seq": null,"templateId": 42},{"id": 28,"name": "手机屏幕尺寸","options": "5寸,5.5寸","seq": null,"templateId": 42},{"id": 32,"name": "机身内存","options": "16G,32G,128G","seq": null,"templateId": 42},{"id": 34,"name": "存储","options": "16G,32G,64G","seq": null,"templateId": 42},{"id": 36,"name": "像素","options": "300万像素,800万像素","seq": 1,"templateId": 42},{"id": 38,"name": "颜色","options": "红,绿,蓝,紫,白,黑","seq": 11,"templateId": 42},{"id": 39,"name": "测试","options": "实施,学习,实施,测试,显示,s11","seq": 1,"templateId": 42}]
}
http://localhost:18081/para/category/11156
{"flag": true,"code": 20000,"message": "查询分类对应的品牌成功!","data": [{"id": 1,"name": "出厂年份","options": "2001,2002,2004,2005","seq": 1,"templateId": 42},{"id": 2,"name": "版本","options": "10,20,30","seq": 11,"templateId": 42}]
}
上面接口测试都正确,OK
----------------------------------------------------------------------------------------------------------------------------------------------------------
SPU+SKU保存
保存商品数据的时候,需要保存Spu和Sku,一个Spu对应多个Sku,我们可以先构建一个Goods对象,
将Spu
和List<Sku>
组合到一起,前端将2者数据提交过来,再实现添加操作。
Pojo改造
修改changgou-service-goods-api工程创建组合实体类,创建com.changgou.goods.pojo.Goods,代码如下:
package com.changgou.goods.pojo;import java.io.Serializable;
import java.util.List;public class Goods implements Serializable {//SPUprivate Spu spu;//SKU集合private List<Sku> skuList;public Spu getSpu() {return spu;}public void setSpu(Spu spu) {this.spu = spu;}public List<Sku> getSkuList() {return skuList;}public void setSkuList(List<Sku> skuList) {this.skuList = skuList;}
}
修改com.changgou.goods.service.SpuService接口,添加保存Goods方法,代码如下:
/*** 保存商品* @param goods*/
void saveGoods(Goods goods);
修改com.changgou.goods.service.impl.SpuServiceImpl类,添加保存Goods的方法实现,代码如下:
@Autowired
private IdWorker idWorker;@Autowired
private CategoryMapper categoryMapper;@Autowired
private BrandMapper brandMapper;@Autowired
private SkuMapper skuMapper;/*** 添加商品信息* @param goods*/
@Override
public void saveGoods(Goods goods) {//增加SpuSpu spu = goods.getSpu();spu.setId(idWorker.nextId());//其他属性不填,数据库有默认值,这里可以省略spuMapper.insertSelective(spu);//增加SkuDate date = new Date();Category category = categoryMapper.selectByPrimaryKey(spu.getCategory3Id());Brand brand = brandMapper.selectByPrimaryKey(spu.getBrandId());//获取Sku集合List<Sku> skus = goods.getSkuList();//循环将数据加入到数据库for (Sku sku : skus) {//防止空指针if(StringUtils.isEmpty(sku.getSpec())){sku.setSpec("{}");}//构建SKU名称,采用SPU+规格值组装//获取Spu的名字String name = spu.getName();//将规格转换成MapMap<String,String> specMap = JSON.parseObject(sku.getSpec(), Map.class);//循环组装Sku的名字for (Map.Entry<String, String> entry : specMap.entrySet()) {name+=" "+entry.getValue();}sku.setName(name);//IDsku.setId(idWorker.nextId());//SpuIdsku.setSpuId(spu.getId());//创建日期sku.setCreateTime(date);//修改日期sku.setUpdateTime(date);//商品分类IDsku.setCategoryId(spu.getCategory3Id());//分类名字sku.setCategoryName(category.getName());//品牌名字sku.setBrandName(brand.getName());//增加skuMapper.insertSelective(sku);}
}
修改com.changgou.goods.controller.SpuController,增加保存Goods方法,代码如下:
/**** 添加Goods* @param goods* @return*/
@PostMapping("/save")
public Result save(@RequestBody Goods goods){spuService.saveGoods(goods);return new Result(true,StatusCode.OK,"保存成功");
}
测试:启动EurekaApplication,启动GoodsApplication
目前前端页面没整合,暂时用测试数据测试
{"skuList": [{"alertNum": 10,"brandName": "华为AAA","categoryId": 64,"commentNum": 0,"image": "","images": "","name": "华为P30手机","num": 5,"price": 1000,"saleNum": 0,"sn": "No1001","spec": "{\"颜色\":\"红色\",\"网络\":\"移动3G\"}","weight": 0}],"spu": {"brandId": 8557,"caption": "华为手机大促销","category1Id": 1,"category2Id": 59,"category3Id": 64,"commentNum": 0,"freightId": 0,"images": ".jpg,.jpg","introduction": "华为产品世界最强","isEnableSpec": "1","isMarketable": "1","name": "华为高档手机","specItems": "{\"颜色\":[\"红\",\"绿\"],\"机身内存\":[\"64G\",\"8G\"]}","paraItems": "{\"赠品\":\"充电器\",\"出厂年份\":\"2019\"}","saleNum": 0,"saleService": "一年包换","sn": "No10001","status": "1","templateId": 42}
}
http://localhost:18081/spu/save
postman测试:成功
----------------------------------------------------------------------------------------------------------------------------------------------------------
根据ID查询商品
/**** 根据ID查询Goods* @param id* @return*/
@GetMapping("/goods/{id}")
public Result<Goods> findGoodsById(@PathVariable Long id){//根据ID查询Goods(SPU+SKU)信息Goods goods = spuService.findGoodsById(id);return new Result<Goods>(true,StatusCode.OK,"查询成功",goods);
}/**** 根据SPU的ID查找SPU以及对应的SKU集合* @param spuId*/
Goods findGoodsById(Long spuId);/**** 根据SpuID查询goods信息* @param spuId* @return*/
@Override
public Goods findGoodsById(Long spuId) {//查询SpuSpu spu = spuMapper.selectByPrimaryKey(spuId);//查询List<Sku>Sku sku = new Sku();sku.setSpuId(spuId);List<Sku> skus = skuMapper.select(sku);//封装GoodsGoods goods = new Goods();goods.setSkuList(skus);goods.setSpu(spu);return goods;
}
测试:http://localhost:18081/spu/goods/1400819467537088512
{"flag": true,"code": 20000,"message": "查询成功","data": {"spu": {"id": 1400819467537088512,"sn": "No10001","name": "华为高档手机","caption": "华为手机大促销","brandId": 8557,"category1Id": 1,"category2Id": 59,"category3Id": 64,"templateId": 42,"freightId": 0,"image": null,"images": ".jpg,.jpg","saleService": "一年包换","introduction": "华为产品世界最强","specItems": "{\"颜色\":[\"红\",\"绿\"],\"机身内存\":[\"64G\",\"8G\"]}","paraItems": "{\"赠品\":\"充电器\",\"出厂年份\":\"2019\"}","saleNum": 0,"commentNum": 0,"isMarketable": "1","isEnableSpec": "1","isDelete": "0","status": "1"},"skuList": [{"id": 1400819472301817856,"sn": "No1001","name": "华为高档手机 红色 移动3G","price": 1000,"num": 5,"alertNum": 10,"image": "","images": "","weight": 0,"createTime": "2021-06-04T14:19:23.000+0000","updateTime": "2021-06-04T14:19:23.000+0000","spuId": 1400819467537088512,"categoryId": 64,"categoryName": "语言文字","brandName": "华为","spec": "{\"颜色\":\"红色\",\"网络\":\"移动3G\"}","saleNum": 0,"commentNum": 0,"status": "1"}]}
}
保存修改
修改changgou-service-goods的SpuServiceImpl的saveGoods方法,修改添加SPU部分代码:
if(spu.getId()==null){//增加spu.setId(idWorker.nextId());spuMapper.insertSelective(spu);
}else{//修改数据spuMapper.updateByPrimaryKeySelective(spu);//删除该Spu的SkuSku sku = new Sku();sku.setSpuId(spu.getId());skuMapper.delete(sku);
}
测试:http://localhost:18081/spu/save
{"spu": {"id": 1401029000662351872,"sn": "No10001","name": "华为高档手机20210605哈哈哈1999","caption": "华为手机大促销","brandId": 8557,"category1Id": 1,"category2Id": 59,"category3Id": 64,"templateId": 42,"freightId": 0,"image": null,"images": ".jpg,.jpg","saleService": "一年包换","introduction": "华为产品世界最强","specItems": "{\"颜色\":[\"红\",\"绿\"],\"机身内存\":[\"64G\",\"8G\"]}","paraItems": "{\"赠品\":\"充电器\",\"出厂年份\":\"2019\"}","saleNum": 0,"commentNum": 0,"isMarketable": "1","isEnableSpec": "1","isDelete": "0","status": "1"},"skuList": [{"id": 1400819472301817856,"sn": "No1001","name": "华为高档手机 红色 移动3G","price": 1000,"num": 5,"alertNum": 10,"image": "","images": "","weight": 0,"createTime": "2021-06-04T14:19:23.000+0000","updateTime": "2021-06-04T14:19:23.000+0000","spuId": 1400819467537088512,"categoryId": 64,"categoryName": "语言文字","brandName": "华为","spec": "{\"颜色\":\"红色\",\"网络\":\"移动3G\"}","saleNum": 0,"commentNum": 0,"status": "1"}]}
修改SKU库存
后面补充。。。。
商品审核
商品新增后,审核状态为0(未审核),默认为下架状态。
审核商品,需要校验是否是被删除的商品,如果未删除则修改审核状态为1,并自动上架
下架商品,需要校验是否是被删除的商品,如果未删除则修改上架状态为0
上架商品,需要审核通过的商品
/*** 审核* @param id* @return*/
@PutMapping("/audit/{id}")
public Result audit(@PathVariable Long id){spuService.audit(id);return new Result(true,StatusCode.OK,"审核成功");
}/**** 商品审核* @param spuId*/
void audit(Long spuId);/**** 商品审核* @param spuId*/
@Override
public void audit(Long spuId) {//查询商品Spu spu = spuMapper.selectByPrimaryKey(spuId);//判断商品是否已经删除if(spu.getIsDelete().equalsIgnoreCase("1")){throw new RuntimeException("该商品已经删除!");}//实现上架和审核spu.setStatus("1"); //审核通过spu.setIsMarketable("1"); //上架spuMapper.updateByPrimaryKeySelective(spu);
}
下架商品
/*** 下架* @param id* @return*/
@PutMapping("/pull/{id}")
public Result pull(@PathVariable Long id){spuService.pull(id);return new Result(true,StatusCode.OK,"下架成功");
}/**** 商品下架* @param spuId*/
void pull(Long spuId);/*** 商品下架* @param spuId*/
@Override
public void pull(Long spuId) {Spu spu = spuMapper.selectByPrimaryKey(spuId);if(spu.getIsDelete().equals("1")){throw new RuntimeException("此商品已删除!");}spu.setIsMarketable("0");//下架状态spuMapper.updateByPrimaryKeySelective(spu);
}
上架商品
/*** 商品上架* @param id* @return*/
@PutMapping("/put/{id}")
public Result put(@PathVariable Long id){spuService.put(id);return new Result(true,StatusCode.OK,"上架成功");
}/**** 商品上架* @param spuId*/
void put(Long spuId);/**** 商品上架* @param spuId*/
@Override
public void put(Long spuId) {Spu spu = spuMapper.selectByPrimaryKey(spuId);//检查是否删除的商品if(spu.getIsDelete().equals("1")){throw new RuntimeException("此商品已删除!");}if(!spu.getStatus().equals("1")){throw new RuntimeException("未通过审核的商品不能!");}//上架状态spu.setIsMarketable("1");spuMapper.updateByPrimaryKeySelective(spu);
}
批量上架
前端传递一组商品ID,后端进行批量上下架处理
/*** 批量上架* @param ids* @return*/
@PutMapping("/put/many")
public Result putMany(@RequestBody Long[] ids){int count = spuService.putMany(ids);return new Result(true,StatusCode.OK,"上架"+count+"个商品");
}/*** 批量上架* @param ids* @return*/
int putMany(Long[] ids);/**** 批量上架* @param ids:需要上架的商品ID集合* @return*/
@Override
public int putMany(Long[] ids) {Spu spu=new Spu();spu.setIsMarketable("1");//上架//update tb_spu set IsMarketable=1 where id in(ids) and isdelete=0 and is_marketable=0 and status=1Example example=new Example(Spu.class);Example.Criteria criteria = example.createCriteria();criteria.andIn("id", Arrays.asList(ids));//id//下架状态criteria.andEqualTo("isMarketable","0");//审核通过的criteria.andEqualTo("status","1");//非删除的criteria.andEqualTo("isDelete","0");return spuMapper.updateByExampleSelective(spu, example);
}
批量下架
/*** 批量下架* @param ids* @return*/
@PutMapping("/pull/many")
public Result pullMany(@RequestBody Long[] ids){int count = spuService.pullMany(ids);return new Result(true,StatusCode.OK,count+"款商品下架成功");
}/*** 批量下架* @param ids* @return*/
int pullMany(Long[] ids);/*** 批量下架* @param ids 需要下架的商品ID集合* @return*/
@Override
public int pullMany(Long[] ids) {//is_marketable是否上架,0已下架,1已上架//is_delete是否删除,0:未删除,1:已删除//status审核状态,0:未审核,1:已审核,2:审核不通过//批量上架 update tb_spu set is_marketable=1 where id in(ids)and is_delete=0 and is_marketable=0 and status=1//批量下架 update tb_spu set is_marketable=0 where id in(ids) and is_delete=0 and is_marketable=1 and status=1Spu spu=new Spu();spu.setIsMarketable("0");//下架Example example=new Example(Spu.class);Example.Criteria criteria = example.createCriteria();criteria.andIn("id", Arrays.asList(ids));//id//上架状态criteria.andEqualTo("isMarketable","1");//审核通过的criteria.andEqualTo("status","1");//非删除的criteria.andEqualTo("isDelete","0");return spuMapper.updateByExampleSelective(spu, example);
}
启动EurekaApplication,启动GoodsApplication
postman测试批量上架:http://localhost:18081/spu/put/many
//is_marketable是否上架,0已下架,1已上架 //is_delete是否删除,0:未删除,1:已删除 //status审核状态,0:未审核,1:已审核,2:审核不通过
可以看到,这两条数据的状态改成了下架
postman测试批量下架:http://localhost:18081/spu/pull/many
----------------------------------------------------------------------------------------------------------------------------------------------------------
删除与还原商品
商品列表中的删除商品功能,并非真正的删除,而是将删除标记的字段设置为1,
在回收站中有恢复商品的功能,将删除标记的字段设置为0
在回收站中有删除商品的功能,是真正的物理删除。
实现思路
逻辑删除商品,修改spu表is_delete字段为1
商品回收站显示spu表is_delete字段为1的记录
回收商品,修改spu表is_delete字段为0
/*** 逻辑删除* @param id* @return*/
@DeleteMapping("/logic/delete/{id}")
public Result logicDelete(@PathVariable Long id){spuService.logicDelete(id);return new Result(true,StatusCode.OK,"逻辑删除成功!");
}/**** 逻辑删除* @param spuId*/
void logicDelete(Long spuId);/**** 逻辑删除* @param spuId*/
@Override
@Transactional
public void logicDelete(Long spuId) {Spu spu = spuMapper.selectByPrimaryKey(spuId);//检查是否下架的商品if(!spu.getIsMarketable().equals("0")){throw new RuntimeException("必须先下架再删除!");}//删除spu.setIsDelete("1");//未审核spu.setStatus("0");spuMapper.updateByPrimaryKeySelective(spu);
}
还原被删除的商品
/*** 恢复数据* @param id* @return*/
@PutMapping("/restore/{id}")
public Result restore(@PathVariable Long id){spuService.restore(id);return new Result(true,StatusCode.OK,"数据恢复成功!");
}/**** 还原被删除商品* @param spuId*/
void restore(Long spuId);/*** 恢复数据* @param spuId*/
@Override
public void restore(Long spuId) {Spu spu = spuMapper.selectByPrimaryKey(spuId);//检查是否删除的商品if(!spu.getIsDelete().equals("1")){throw new RuntimeException("此商品未删除!");}//未删除spu.setIsDelete("0");//未审核spu.setStatus("0");spuMapper.updateByPrimaryKeySelective(spu);
}
物理删除商品
修改com.changgou.goods.service.impl.SpuServiceImpl的delete方法,代码如下:
/*** 删除* @param id*/
@Override
public void delete(Long id){Spu spu = spuMapper.selectByPrimaryKey(id);//检查是否被逻辑删除 ,必须先逻辑删除后才能物理删除if(!spu.getIsDelete().equals("1")){throw new RuntimeException("此商品不能删除!");}spuMapper.deleteByPrimaryKey(id);
}
商品列表代码生成器已经生成了
代码就不贴了