學習目標
- SPU與SKU概念理解
1 2
SPU:某一款商品的公共屬性 SKU:某款商品的不同參數對應的商品信息[某個商品]
- ==新增商品、修改商品==
1 2
增加:增加SPU和SKU 修改:修改SPU和SKU
- 商品審覈、上架、下架
1 2
審覈:修改審覈狀態 上架下架:修改上架下架狀態
- 刪除商品
1 2
邏輯刪除:修改了刪除狀態 物理刪除:真實刪除了數據
- 找回商品
找回商品:一定是屬於邏輯刪除的商品
1 SPU與SKU
1.1 SPU與SKU概念
SPU = Standard Product Unit (標準產品單位)
-
概念 : SPU 是商品信息聚合的最小單位,是一組可複用、易檢索的標準化信息的集合,該集合描述了一個產品的特性。
-
通俗點講,屬性值、特性相同的貨品就可以稱爲一個 SPU
==同款商品的公共屬性抽取==
例如:**華爲P30 就是一個 SPU**
SKU=stock keeping unit( 庫存量單位)
-
SKU 即庫存進出計量的單位, 可以是以件、盒、托盤等爲單位。
-
SKU 是物理上不可分割的最小存貨單元。在使用時要根據不同業態,不同管理模式來處理。
-
在服裝、鞋類商品中使用最多最普遍。
例如:**華爲P30 紅色 64G 就是一個 SKU**
==某個庫存單位的商品獨有屬性(某個商品的獨有屬性)==
1.2 表結構分析
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 |
2 新增和修改商品
2.1 需求分析
實現商品的新增與修改功能。
(1)第1個步驟,先選擇添加的商品所屬分類
這塊在第2天的代碼中已經有一個根據父節點ID查詢分類信息的方法,參考第2天的4.3.4的findByPrantId方法,首先查詢頂級分類,也就是pid=0,然後根據用戶選擇的分類,將選擇的分類作爲pid查詢子分類。
(2)第2個步驟,填寫SPU的信息
(3)第3個步驟,填寫SKU信息
先進入選擇商品分類 再填寫商品的信息 填寫商品的屬性添加商品。
2.2 實現思路
前端傳遞給後端的數據格式 是一個spu對象和sku列表組成的對象,如下圖:
上圖JSON數據如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
{ "spu": { "name": "這個是商品名稱", "caption": "這個是副標題", "brandId": 12, "category1Id": 558, "category2Id": 559, "category3Id": 560, "freightId": 10, "image": "http://www.qingcheng.com/image/1.jpg", "images": "http://www.qingcheng.com/image/1.jpg,http://www.qingcheng.com/image/2.jpg", "introduction": "這個是商品詳情,html代碼", "paraItems": { "出廠年份": "2019", "贈品": "充電器" }, "saleService": "七天包退,閃電退貨", "sn": "020102331", "specItems": { "顏色": [ "紅", "綠" ], "機身內存": [ "64G", "8G" ] }, "templateId": 42 }, "skuList": [ { "sn": "10192010292", "num": 100, "alertNum": 20, "price": 900000, "spec": { "顏色": "紅", "機身內存": "64G" }, "image": "http://www.qingcheng.com/image/1.jpg", "images": "http://www.qingcheng.com/image/1.jpg,http://www.qingcheng.com/image/2.jpg", "status": "1", "weight": 130 }, { "sn": "10192010293", "num": 100, "alertNum": 20, "price": 600000, "spec": { "顏色": "綠", "機身內存": "8G" }, "image": "http://www.qingcheng.com/image/1.jpg", "images": "http://www.qingcheng.com/image/1.jpg,http://www.qingcheng.com/image/2.jpg", "status": "1", "weight": 130 } ] }
2.3 代碼生成
準備工作:爲了更快的實現代碼編寫,我們可以採用《黑馬代碼生成器》來批量生成代碼,這些代碼就已經實現了我們之前的增刪改查功能。
《黑馬代碼生成器》一款由傳智播客教育集團JavaEE教研團隊開發的基於Freemarker模板引擎的“代碼生成神器”。即便是一個工程幾百個表,也可以瞬間完成基礎代碼的構建!用戶只需建立數據庫表結構,運行main方法就可快速生成可以運行的一整套代碼,可以極大地縮短開發週期,降低人力成本。《黑馬代碼生成器》的誕生主要用於迅速構建生成微服務工程的Pojo、Dao、Service、Controller各層、並且可以生成swagger API模板等。 用戶通過自己開發模板也可以實現生成php、python、C# 、c++、數據庫存儲過程等其它編程語言的代碼。
《黑馬代碼生成器》目前已經開源 地址:https://github.com/shenkunlin/code-template.git
如下圖資料,將其導入到idea中 並執行即可:
使用說明,簡單來說如下圖所示:
2.4 代碼實現
一會兒會用到ID生成,我們可以使用IdWorker,在啓動類GoodsApplication中添加如下代碼,用於創建IdWorker,並將IdWorker交給Spring容器,代碼如下:
1 2 3 4 5 6 7 8
/*** * IdWorker * @return */ @Bean public IdWorker idWorker(){ return new IdWorker(0,0); }
2.4.1 查詢分類
2.4.1.1 分析
在實現商品增加之前,需要先選擇對應的分類,選擇分類的時候,首選選擇一級分類,然後根據選中的分類,將選中的分類作爲查詢的父ID,再查詢對應的子分類集合,因此我們可以在後臺編寫一個方法,根據父類ID查詢對應的分類集合即可。
2.4.1.2 代碼實現
(1)Service層
修改com.changgou.goods.service.CategoryService
添加根據父類ID查詢所有子節點,代碼如下:
1 2 3 4
/*** * 根據分類的父ID查詢子分類節點集合 */ List<Category> findByParentId(Integer pid);
修改com.changgou.goods.service.impl.CategoryServiceImpl
添加上面的實現,代碼如下:
1 2 3 4 5 6 7 8 9 10 11 12
/*** * 根據分類的父節點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); }
(2)Controller層
修改com.changgou.goods.controller.CategoryController
添加根據父ID查詢所有子類集合,代碼如下:
1 2 3 4 5 6 7 8 9
/**** * 根據節點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); }
2.4.2 模板查詢(規格參數組)
同學作業
2.4.2.1 分析
如上圖,當用戶選中了分類後,需要根據分類的ID查詢出對應的模板數據,並將模板的名字顯示在這裏,模板表結構如下:
1 2 3 4 5 6 7
CREATE TABLE `tb_template` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID', `name` varchar(50) DEFAULT NULL COMMENT '模板名稱', `spec_num` int(11) DEFAULT '0' COMMENT '規格數量', `para_num` int(11) DEFAULT '0' COMMENT '參數數量', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=44 DEFAULT CHARSET=utf8;
2.4.2.2 代碼實現
(1)Service層
修改com.changgou.goods.service.TemplateService
接口,添加如下方法根據分類ID查詢模板:
1 2 3 4 5 6
/** * 根據分類ID查詢模板信息 * @param id * @return */ Template findByCategoryId(Integer id);
修改com.changgou.goods.service.impl.TemplateServiceImpl
添加上面方法的實現:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
@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()); }
(2)Controller層
修改com.changgou.goods.controller.TemplateController
,添加根據分類ID查詢模板數據:
1 2 3 4 5 6 7 8 9 10
/*** * 根據分類查詢模板數據 * @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); }
2.4.3 查詢分類品牌數據
2.4.3.1 分析
用戶每次選擇了分類之後,可以根據用戶選擇的分類到tb_category_brand
表中查詢指定的品牌集合ID,然後根據品牌集合ID查詢對應的品牌集合數據,再將品牌集合數據拿到這裏來展示即可實現上述功能。
2.4.3.2 代碼實現
(1)Dao實現
修改com.changgou.goods.dao.BrandMapper
添加根據分類ID查詢對應的品牌數據,代碼如下:
1 2 3 4 5 6 7 8
public interface BrandMapper extends Mapper<Brand> { /*** * 查詢分類對應的品牌集合 */ @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); }
(2)Service層
修改com.changgou.goods.service.BrandService
,添加根據分類ID查詢指定的品牌集合方法,代碼如下:
1 2 3 4 5
/*** * 根據分類ID查詢品牌集合 * @param categoryid:分類ID */ List<Brand> findByCategory(Integer categoryid);
修改com.changgou.goods.service.impl.BrandServiceImpl
添加上面方法的實現,代碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13
/*** * 根據分類ID查詢品牌集合 * @param categoryid:分類ID * @return */ @Override public List<Brand> findByCategory(Integer categoryid) { //1.查詢當前分類所對應的所有品牌信息 //2.根據品牌ID查詢對應的品牌集合 //自己創建DAO實現查詢 return brandMapper.findByCategory(categoryid); }
(3)Controller層
修改,添加根據分類ID查詢對應的品牌數據代碼如下:
1 2 3 4 5 6 7 8 9 10
/*** * 根據分類實現品牌列表查詢 * /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); }
2.4.4 規格查詢
2.4.4.1 分析
用戶選擇分類後,需要根據所選分類對應的模板ID查詢對應的規格,規格表結構如下:
1 2 3 4 5 6 7 8
CREATE TABLE `tb_spec` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID', `name` varchar(50) DEFAULT NULL COMMENT '名稱', `options` varchar(2000) DEFAULT NULL COMMENT '規格選項', `seq` int(11) DEFAULT NULL COMMENT '排序', `template_id` int(11) DEFAULT NULL COMMENT '模板ID', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=40 DEFAULT CHARSET=utf8;
2.4.4.2 代碼實現
(1)Service層
修改com.changgou.goods.service.SpecService
添加根據分類ID查詢規格列表,代碼如下:
1 2 3 4 5 6
/*** * 根據分類ID查詢規格列表 * @param categoryid * @return */ List<Spec> findByCategoryId(Integer categoryid);
修改com.changgou.goods.service.impl.SpecServiceImpl
添加上面方法的實現,代碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
@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); }
(2)Controller層
修改com.changgou.goods.controller.SpecController
添加根據分類ID查詢規格數據,代碼如下:
1 2 3 4 5 6 7 8 9
/*** * 根據分類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); }
2.4.5 參數列表查詢
2.4.5.1 分析
當用戶選中分類後,需要根據分類的模板ID查詢對應的參數列表,參數表結構如下:
1 2 3 4 5 6 7 8
CREATE TABLE `tb_para` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id', `name` varchar(50) DEFAULT NULL COMMENT '名稱', `options` varchar(2000) DEFAULT NULL COMMENT '選項', `seq` int(11) DEFAULT NULL COMMENT '排序', `template_id` int(11) DEFAULT NULL COMMENT '模板ID', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
2.4.5.2 代碼實現
(1)Service層
修改com.changgou.goods.service.ParaService
添加根據分類ID查詢參數列表,代碼如下:
1 2 3 4 5 6
/*** * 根據分類ID查詢參數列表 * @param id * @return */ List<Para> findByCategoryId(Integer id);
修改com.changgou.goods.service.impl.ParaServiceImpl
添加上面方法的實現,代碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
@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); }
(2)Controller層
修改com.changgou.goods.controller.ParaController
,添加根據分類ID查詢參數列表,代碼如下:
1 2 3 4 5 6 7 8 9 10 11 12
/** * 根據分類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; }
2.4.6 SPU+SKU保存
2.4.6.1 分析
保存商品數據的時候,需要保存Spu和Sku,一個Spu對應多個Sku,我們可以先構建一個Goods對象,將Spu
和List<Sku>
組合到一起,前端將2者數據提交過來,再實現添加操作。
2.4.62 代碼實現
(1)Pojo改造
修改changgou-service-goods-api工程創建組合實體類,創建com.changgou.goods.pojo.Goods,代碼如下:
1 2 3 4 5 6 7 8
public class Goods implements Serializable { //SPU private Spu spu; //SKU集合 private List<Sku> skuList; //..get..set..toString }
(2) 業務層
修改com.changgou.goods.service.SpuService接口,添加保存Goods方法,代碼如下:
1 2 3 4 5
/** * 保存商品 * @param goods */ void saveGoods(Goods goods);
修改com.changgou.goods.service.impl.SpuServiceImpl類,添加保存Goods的方法實現,代碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
@Autowired private IdWorker idWorker; @Autowired private CategoryMapper categoryMapper; @Autowired private BrandMapper brandMapper; @Autowired private SkuMapper skuMapper; /*** * 保存Goods * @param goods */ @Override public void saveGoods(Goods goods) { //增加Spu Spu spu = goods.getSpu(); spu.setId(idWorker.nextId()); spuMapper.insertSelective(spu); //增加Sku Date date = new Date(); Category category = categoryMapper.selectByPrimaryKey(spu.getCategory3Id()); Brand brand = brandMapper.selectByPrimaryKey(spu.getBrandId()); //獲取Sku集合 List<Sku> skus = goods.getSkus(); //循環將數據加入到數據庫 for (Sku sku : skus) { //構建SKU名稱,採用SPU+規格值組裝 if(StringUtils.isEmpty(sku.getSpec())){ sku.setSpec("{}"); } //獲取Spu的名字 String name = spu.getName(); //將規格轉換成Map Map<String,String> specMap = JSON.parseObject(sku.getSpec(), Map.class); //循環組裝Sku的名字 for (Map.Entry<String, String> entry : specMap.entrySet()) { name+=" "+entry.getValue(); } sku.setName(name); //ID sku.setId(idWorker.nextId()); //SpuId sku.setSpuId(spu.getId()); //創建日期 sku.setCreateTime(date); //修改日期 sku.setUpdateTime(date); //商品分類ID sku.setCategoryId(spu.getCategory3Id()); //分類名字 sku.setCategoryName(category.getName()); //品牌名字 sku.setBrandName(brand.getName()); //增加 skuMapper.insertSelective(sku); } }
(3)控制層
修改com.changgou.goods.controller.SpuController,增加保存Goods方法,代碼如下:
1 2 3 4 5 6 7 8 9 10
/*** * 添加Goods * @param goods * @return */ @PostMapping("/save") public Result save(@RequestBody Goods goods){ spuService.saveGoods(goods); return new Result(true,StatusCode.OK,"保存成功"); }
測試數據
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
{ "skuList": [ { "alertNum": 10, "brandName": "華爲", "categoryId": 64, "commentNum": 0, "image": "http://www.baidu.com", "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": "http://www.qingcheng.com/image/1.jpg,http://www.qingcheng.com/image/2.jpg", "introduction": "華爲產品世界最強", "isEnableSpec": "1", "isMarketable": "1", "name": "string", "specItems": "{\"顏色\":[\"紅\",\"綠\"],\"機身內存\":[\"64G\",\"8G\"]}", "paraItems": "{\"贈品\":\"充電器\",\"出廠年份\":\"2019\"}", "saleNum": 0, "saleService": "一年包換", "sn": "No10001", "status": "1", "templateId": 42 } }
2.4.7 根據ID查詢商品
2.4.7.1 需求分析
需求:根據id 查詢SPU和SKU列表 ,顯示效果如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
{ "spu": { "brandId": 0, "caption": "111", "category1Id": 558, "category2Id": 559, "category3Id": 560, "commentNum": null, "freightId": null, "id": 149187842867993, "image": null, "images": null, "introduction": null, "isDelete": null, "isEnableSpec": "0", "isMarketable": "1", "name": "黑馬智能手機", "paraItems": null, "saleNum": null, "saleService": null, "sn": null, "specItems": null, "status": null, "templateId": 42 }, "skuList": [{ "alertNum": null, "brandName": "金立(Gionee)", "categoryId": 560, "categoryName": "手機", "commentNum": null, "createTime": "2018-11-06 10:17:08", "id": 1369324, "image": null, "images": "blob:http://localhost:8080/ec04d1a5-d865-4e7f-a313-2e9a76cfb3f8", "name": "黑馬智能手機", "num": 100, "price": 900000, "saleNum": null, "sn": "", "spec": null, "spuId": 149187842867993, "status": "1", "updateTime": "2018-11-06 10:17:08", "weight": null },{ "alertNum": null, "brandName": "金立(Gionee)", "categoryId": 560, "categoryName": "手機", "commentNum": null, "createTime": "2018-11-06 10:17:08", "id": 1369325, "image": null, "images": "blob:http://localhost:8080/ec04d1a5-d865-4e7f-a313-2e9a76cfb3f8", "name": "黑馬智能手機", "num": 100, "price": 900000, "saleNum": null, "sn": "", "spec": null, "spuId": 149187842867993, "status": "1", "updateTime": "2018-11-06 10:17:08", "weight": null } ] }
2.4.7.2 代碼實現
(1)業務層
修改qingcheng-service-goods工程,修改com.changgou.goods.service.SpuService接口,添加根據ID查找方法findGoodsById代碼如下:
1 2 3 4 5
/*** * 根據SPU的ID查找SPU以及對應的SKU集合 * @param spuId */ Goods findGoodsById(Long spuId);
修改qingcheng-service-goods工程,修改com.changgou.goods.service.impl.SpuServiceImpl類,添加根據ID查找findGoodsById方法,代碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*** * 根據SpuID查詢goods信息 * @param spuId * @return */ @Override public Goods findGoodsById(Long spuId) { //查詢Spu Spu spu = spuMapper.selectByPrimaryKey(spuId); //查詢List<Sku> Sku sku = new Sku(); sku.setSpuId(spuId); List<Sku> skus = skuMapper.select(sku); //封裝Goods Goods goods = new Goods(); goods.setSkus(skus); goods.setSpu(spu); return goods; }
(2)控制層
修改com.changgou.goods.controller.SpuController,修改findById方法,代碼如下:
1 2 3 4 5 6 7 8 9 10 11
/*** * 根據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); }
測試:http://localhost:18081/spu/goods/1088256029394866176
2.4.8 保存修改
修改changgou-service-goods的SpuServiceImpl的saveGoods方法,修改添加SPU部分代碼:
上圖代碼如下:
1 2 3 4 5 6 7 8 9 10 11 12
if(spu.getId()==null){ //增加 spu.setId(idWorker.nextId()); spuMapper.insertSelective(spu); }else{ //修改數據 spuMapper.updateByPrimaryKeySelective(spu); //刪除該Spu的Sku Sku sku = new Sku(); sku.setSpuId(spu.getId()); skuMapper.delete(sku); }
2.4.9 修改SKU庫存
(學員實現)
3 商品審覈與上下架
3.1 需求分析
商品新增後,審覈狀態爲0(未審覈),默認爲下架狀態。
審覈商品,需要校驗是否是被刪除的商品,如果未刪除則修改審覈狀態爲1,並自動上架
下架商品,需要校驗是否是被刪除的商品,如果未刪除則修改上架狀態爲0
上架商品,需要審覈通過的商品
3.2 實現思路
(1)按照ID查詢SPU信息
(2)判斷修改審覈、上架和下架狀態
(3)保存SPU
3.3 代碼實現
3.3.1 商品審覈
實現審覈通過,自動上架。
(1)業務層
修改修改changgou-service-goods工程的com.changgou.goods.service.SpuService接口,添加審覈方法,代碼如下:
1 2 3 4 5
/*** * 商品審覈 * @param spuId */ void audit(Long spuId);
修改changgou-service-goods工程的com.changgou.goods.service.impl.SpuServiceImpl類,添加audit方法,代碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/*** * 商品審覈 * @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); }
(2)控制層
修改com.changgou.goods.controller.SpuController,新增audit方法,代碼如下:
1 2 3 4 5 6 7 8 9 10
/** * 審覈 * @param id * @return */ @PutMapping("/audit/{id}") public Result audit(@PathVariable Long id){ spuService.audit(id); return new Result(true,StatusCode.OK,"審覈成功"); }
3.3.2 下架商品
(1)業務層
修改com.changgou.goods.service.SpuService接口,添加pull方法,用於商品下架,代碼如下:
1 2 3 4 5
/*** * 商品下架 * @param spuId */ void pull(Long spuId);
修改com.changgou.goods.service.impl.SpuServiceImpl,添加如下方法:
1 2 3 4 5 6 7 8 9 10 11 12 13
/** * 商品下架 * @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); }
(2)控制層
修改com.changgou.goods.controller.SpuController,添加pull方法,代碼如下:
1 2 3 4 5 6 7 8 9 10
/** * 下架 * @param id * @return */ @PutMapping("/pull/{id}") public Result pull(@PathVariable Long id){ spuService.pull(id); return new Result(true,StatusCode.OK,"下架成功"); }
3.3.3 上架商品
必須是通過審覈的商品才能上架
(1)業務層
修改com.changgou.goods.service.SpuService,添加put方法,代碼如下:
1 2 3 4 5
/*** * 商品上架 * @param spuId */ void put(Long spuId);
修改com.changgou.goods.service.impl.SpuServiceImpl,添加put方法實現,代碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/*** * 商品上架 * @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); }
(2)控制層
修改com.changgou.goods.controller.SpuController,添加put方法代碼如下:
1 2 3 4 5 6 7 8 9 10
/** * 商品上架 * @param id * @return */ @PutMapping("/put/{id}") public Result put(@PathVariable Long id){ spuService.put(id); return new Result(true,StatusCode.OK,"上架成功"); }
3.3.4 批量上架
前端傳遞一組商品ID,後端進行批量上下架處理
(1)業務層
修改com.changgou.goods.service.SpuService接口,代碼如下:
int putMany(Long[] ids);
修改com.changgou.goods.service.impl.SpuServiceImpl,添加批量上架方法實現,代碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*** * 批量上架 * @param ids:需要上架的商品ID集合 * @return */ @Override public int putMany(Long[] ids) { Spu spu=new Spu(); spu.setIsMarketable("1");//上架 //批量修改 Example 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); }
(2)控制層
修改com.changgou.goods.controller.SpuController,天啊及批量上架方法,代碼如下:
1 2 3 4 5 6 7 8 9 10
/** * 批量上架 * @param ids * @return */ @PutMapping("/put/many") public Result putMany(@RequestBody Long[] ids){ int count = spuService.putMany(ids); return new Result(true,StatusCode.OK,"上架"+count+"個商品"); }
使用Postman測試:
3.3.5 批量下架
學員實現
4 刪除與還原商品
4.1 需求分析
請看管理後臺的靜態原型
商品列表中的刪除商品功能,並非真正的刪除,而是將刪除標記的字段設置爲1,
在回收站中有恢復商品的功能,將刪除標記的字段設置爲0
在回收站中有刪除商品的功能,是真正的物理刪除。
4.2 實現思路
邏輯刪除商品,修改spu表is_delete字段爲1
商品回收站顯示spu表is_delete字段爲1的記錄
回收商品,修改spu表is_delete字段爲0
4.3 代碼實現
4.3.1 邏輯刪除商品
(1)業務層
修改com.changgou.goods.service.SpuService接口,增加logicDelete方法,代碼如下:
1 2 3 4 5
/*** * 邏輯刪除 * @param spuId */ void logicDelete(Long spuId);
修改com.changgou.goods.service.impl.SpuServiceImpl,添加logicDelete方法實現,代碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/*** * 邏輯刪除 * @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); }
(2)控制層
修改com.changgou.goods.controller.SpuController,添加logicDelete方法,如下:
1 2 3 4 5 6 7 8 9 10
/** * 邏輯刪除 * @param id * @return */ @DeleteMapping("/logic/delete/{id}") public Result logicDelete(@PathVariable Long id){ spuService.logicDelete(id); return new Result(true,StatusCode.OK,"邏輯刪除成功!"); }
4.3.2 還原被刪除的商品
(1)業務層
修改com.changgou.goods.service.SpuService接口,添加restore方法代碼如下:
1 2 3 4 5
/*** * 還原被刪除商品 * @param spuId */ void restore(Long spuId);
修改com.changgou.goods.service.impl.SpuServiceImpl類,添加restore方法,代碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/** * 恢復數據 * @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); }
(2)控制層
修改com.changgou.goods.controller.SpuController,添加restore方法,代碼如下:
1 2 3 4 5 6 7 8 9 10
/** * 恢復數據 * @param id * @return */ @PutMapping("/restore/{id}") public Result restore(@PathVariable Long id){ spuService.restore(id); return new Result(true,StatusCode.OK,"數據恢復成功!"); }
4.3.3 物理刪除商品
修改com.changgou.goods.service.impl.SpuServiceImpl的delete方法,代碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13
/** * 刪除 * @param id */ @Override public void delete(Long id){ Spu spu = spuMapper.selectByPrimaryKey(id); //檢查是否被邏輯刪除 ,必須先邏輯刪除後才能物理刪除 if(!spu.getIsDelete().equals("1")){ throw new RuntimeException("此商品不能刪除!"); } spuMapper.deleteByPrimaryKey(id); }
5 商品列表
5.1 需求分析
如圖所示 展示商品的列表。並實現分頁。
思路:
1 2
根據查詢的條件 分頁查詢 並返回分頁結果即可。 分頁查詢 採用 pagehelper ,條件查詢 通過map進行封裝傳遞給後臺即可。
5.2 代碼實現
在代碼生成器生成的代碼中已經包含了該實現,這裏就省略了。
控制層(SpuController):
1 2 3 4 5 6 7 8 9 10 11 12 13
/*** * Spu分頁條件搜索實現 * @param spu * @param page * @param size * @return */ @PostMapping(value = "/search/{page}/{size}" ) public Result<PageInfo> findPage(@RequestBody(required = false) Spu spu, @PathVariable int page, @PathVariable int size){ //執行搜索 PageInfo<Spu> pageInfo = spuService.findPage(spu, page, size); return new Result(true,StatusCode.OK,"查詢成功",pageInfo); }
其他每層代碼,代碼生成器已經生成,這裏就不再列出來了。