SpringBoot實戰電商項目mall(30k+star)地址:github.com/macrozheng/…前端
原來的商品SKU設計存在着兩個問題,一個是SKU表設計上面比較固化,沒法擴展。另外一個是當修改了商品信息以後,商品SKU的ID會發生變化,因爲購物車表和訂單商品表都關聯了商品SKU的ID,這樣就會致使匹配不上。最近對這兩個問題作了點優化,下面來聊聊優化的思路。java
首先咱們來了解下商品SPU和SKU的概念,可能不少沒有接觸過電商的朋友都不瞭解。git
舉個例子:好比說如今有個手機商品叫小米8,小米8有不一樣的屬性,好比有它有黑色和藍色的,有32G和64G版本的。此時小米8
就是一個SPU,而小米8黑色64G
就是一個SKU。github
商品的SKU信息是存儲在pms_sku_stock
表中的,使用sp一、sp二、sp3這三個屬性來存儲商品的銷售屬性,這樣作很不靈活,也難以擴展。數據庫
這種作法也帶來了後續的問題,好比咱們的購物車和訂單都會須要存儲銷售屬性,這樣的話都會須要添加sp一、sp二、sp3的屬性。json
因爲商品的銷售屬性是動態的,無法肯定到底有多少個,此時咱們能夠改用JSON格式來存儲,在pms_sku_stock
表中添加了sp_data
字段。數組
sp_data
存儲的就是一個JSON數組,好比顏色爲黑色,容量爲32G的手機存儲信息以下。app
[
{
"key": "顏色",
"value": "黑色"
},
{
"key": "容量",
"value": "32G"
}
]
複製代碼
這樣修改之後,在原來的購物車表oms_cart_item
和訂單商品表oms_order_item
中就均可以用JSON格式來存儲銷售屬性了,使用的是product_attr
字段。ide
商品的SKU信息做爲商品的關聯信息,在修改商品信息時會同時進行修改。之前的作法是直接刪除該商品的全部SKU信息,再從新添加。這樣就會致使商品SKU中的ID被修改,因爲在購物車和訂單商品中關聯了商品SKU的ID,就會致使原來的ID失效的問題。下面是原來修改商品中SKU信息的代碼。學習
/** * 商品管理Service實現類 * Created by macro on 2018/4/26. */
@Service
public class PmsProductServiceImpl implements PmsProductService {
@Override
public int update(Long id, PmsProductParam productParam) {
//省略若干代碼...
//刪除該商品關聯的SKU
PmsSkuStockExample skuStockExample = new PmsSkuStockExample();
skuStockExample.createCriteria().andProductIdEqualTo(id);
skuStockMapper.deleteByExample(skuStockExample);
handleSkuStockCode(productParam.getSkuStockList(),id);
//插入傳入的全部SKU
relateAndInsertList(skuStockDao, productParam.getSkuStockList(), id);
}
}
複製代碼
首先咱們須要和前端約定下,新增的商品SKU信息不傳ID,要修改的商品SKU信息傳ID,刪除的直接不傳SKU信息。而後咱們能夠根據傳入的SKU信息來肯定須要新增、修改、刪除的SKU信息,這樣就能夠作到在更新商品SKU信息時,不改變原來商品SKU的ID了,具體流程以下。
具體代碼實現以下:
/** * 商品管理Service實現類 * Created by macro on 2018/4/26. */
@Service
public class PmsProductServiceImpl implements PmsProductService {
private void handleUpdateSkuStockList(Long id, PmsProductParam productParam) {
//當前的sku信息
List<PmsSkuStock> currSkuList = productParam.getSkuStockList();
//當前沒有sku直接刪除
if(CollUtil.isEmpty(currSkuList)){
PmsSkuStockExample skuStockExample = new PmsSkuStockExample();
skuStockExample.createCriteria().andProductIdEqualTo(id);
skuStockMapper.deleteByExample(skuStockExample);
return;
}
//獲取初始sku信息
PmsSkuStockExample skuStockExample = new PmsSkuStockExample();
skuStockExample.createCriteria().andProductIdEqualTo(id);
List<PmsSkuStock> oriStuList = skuStockMapper.selectByExample(skuStockExample);
//獲取新增sku信息
List<PmsSkuStock> insertSkuList = currSkuList.stream().filter(item->item.getId()==null).collect(Collectors.toList());
//獲取須要更新的sku信息
List<PmsSkuStock> updateSkuList = currSkuList.stream().filter(item->item.getId()!=null).collect(Collectors.toList());
List<Long> updateSkuIds = updateSkuList.stream().map(PmsSkuStock::getId).collect(Collectors.toList());
//獲取須要刪除的sku信息
List<PmsSkuStock> removeSkuList = oriStuList.stream().filter(item-> !updateSkuIds.contains(item.getId())).collect(Collectors.toList());
handleSkuStockCode(insertSkuList,id);
handleSkuStockCode(updateSkuList,id);
//新增sku
if(CollUtil.isNotEmpty(insertSkuList)){
relateAndInsertList(skuStockDao, insertSkuList, id);
}
//刪除sku
if(CollUtil.isNotEmpty(removeSkuList)){
List<Long> removeSkuIds = removeSkuList.stream().map(PmsSkuStock::getId).collect(Collectors.toList());
PmsSkuStockExample removeExample = new PmsSkuStockExample();
removeExample.createCriteria().andIdIn(removeSkuIds);
skuStockMapper.deleteByExample(removeExample);
}
//修改sku
if(CollUtil.isNotEmpty(updateSkuList)){
for (PmsSkuStock pmsSkuStock : updateSkuList) {
skuStockMapper.updateByPrimaryKeySelective(pmsSkuStock);
}
}
}
}
複製代碼
若是咱們要在數據庫中存儲一些格式不固定的屬性時,能夠採用JSON的形式進行存儲。對於關聯屬性的修改,能夠經過一些邏輯操做來實現不改變原有ID的修改。
mall項目全套學習教程連載中,關注公衆號第一時間獲取。