# 1. 背景了解
在看具體的數據庫實體設計之前,我們先一起了解下**電商的名詞定義**
## 1.1 名詞定義
參考 [《產品 SKU 是什么意思?與之相關的還有哪些?》](https://www.zhihu.com/question/19841574) 整理。
**SKU:Stock Keeping Unit**
中文翻譯為庫存單位。SKU 從**庫存**視角,以庫存進出為單位,可以是件、瓶、箱等等。
例如,iPhone 手機,按照規格( 顏色 + 內存 )可以組合出如下多個 SKU :
| SKU | 顏色 | 內存 |
| ---- | ---- | ---- |
| A | 白色 | 16G |
| B | 白色 | 64G |
| C | 黑色 | 16G |
| D | 黑色 | 64G |
可以看出,顏色(白色、黑色)與內存(16G、64G)組合排列出四種 iPhone SKU。
**SPU:Standard Product Unit**
中文翻譯為標準產品單位。SPU 從**產品**視角,是產品信息聚合的**最小單位**,是一組可復用、易檢索的標準化信息的集合,該集合描述了一個產品的特性。通俗點講,屬性值、特性相同的商品就可以被稱為一個 SPU 。例如 iPhone 8 就是一個 SPU ,iPhone 8 Plus 也是一個 SPU ,這個與**商家**無關,與顏色、款式、套餐等**規格**無關。
**商品**:
商家出售某個 SPU ,那么這就是一個商品。商品在 SPU 之上,增加了銷售價格、促銷活動、運費等等信息。另外,**一個商品可以包含多個 SKU**。
**總結**

------
現實的場景往往比定義復雜的多,在本文中,**SKU 代表銷售的單元**。主要考慮如下兩方面:
- 實際我們看到的商品詳情頁,購買的是一個**銷售組合單元**。例如,很多商家會打包 【iPhone X :銀色-64G-套餐三】,其中套餐三為贈送貼膜 + 保護殼等等,當然價格上會更貴。這明顯就違背了我們上述提到 SKU 庫存的概念,已經變成了多個 SKU 的銷售組合單元。
- 一個商家會在不同平臺銷售商品,例如三只松鼠,其在天貓、京東等等平臺都有官方旗艦店,同時也供貨給其他渠道商,那么實際關系會變成如下圖所示: 通過這樣的方式,三只松鼠在不同的平臺,定義不同的價格,設置不同的促銷信息等等個性化的運營。
------
**那么注意了**!!!
**下文開始,SKU 代表銷售的單元**
**下文開始,SKU 代表銷售的單元**
**下文開始,SKU 代表銷售的單元**
## 1.2 界面
1. 商城端-購買頁

2. 運營后臺-商品發布頁 
# 2. 數據庫實體
整體實體類關系如下圖:

全部實體可在數據庫中查閱。
## 2.1 Product
Product 字段較多,我們進行簡單的切塊。
### 2.1.1 基礎字段
```java
@Data
@TableName("tz_prod")
public class Product implements Serializable {
/**
* 商品ID
*/
@TableId
private Long prodId;
/**
* 店鋪id
*/
private Long shopId;
/**
* 商品名稱
*/
private String prodName;
/**
* 簡要描述,賣點等
*/
private String brief;
/**
* 商品主圖
*/
private String pic;
/**
* 商品圖片
*/
private String imgs;
/**
* 默認是1,表示正常狀態, -1表示刪除, 0下架
*/
private Integer status;
/**
* 商品分類
*/
private Long categoryId;
/**
* 已經銷售數量
*/
private Integer soldNum;
/**
* 錄入時間
*/
private Date createTime;
/**
* 修改時間
*/
private Date updateTime;
/**
* 詳細描述
*/
private String content;
/**
* 上架時間
*/
private Date putawayTime;
@Data
public static class DeliveryModeVO {
/**
* 用戶自提
*/
private Boolean hasUserPickUp;
/**
* 店鋪配送
*/
private Boolean hasShopDelivery;
}
}
```
- `prodId` ,商品id,數據庫自增。
- `shopId` ,店鋪編號,支持多商戶( 店鋪 )。
- `categoryId` ,商品所在分類id,每個商品都有自己所屬的分類
### 2.1.2 價格庫存
```java
/**
* 庫存量
* 基于 sku 的庫存數量累加
*/
private Integer totalStocks;
/**
* 原價
*/
private Double oriPrice;
/**
* 現價
*/
private Double price;
```
- 在我們的數據庫中規定,所有的商品都是具有sku的,就算是只有一種規格的商品,所以`product`里面的庫存數量為所有sku庫存數量的總和
- `price` ,商品價格為元,這里使用`Double`而沒有使用`BigDecimal `,而數據庫中使用`decimal` 進行存儲,所以在數據庫中是可以進行直接進行運算的,而在java當中需要使用`com.yami.shop.common.util.Arith`進行運算 。
### 2.1.3 運費信息
```java
/**
* 配送方式json
*/
private String deliveryMode;
/**
* 運費模板id
*/
private Long deliveryTemplateId;
@Data
public static class DeliveryModeVO {
/**
* 用戶自提
*/
private Boolean hasUserPickUp;
/**
* 店鋪配送
*/
private Boolean hasShopDelivery;
}
```
- 根據` deliveryMode `標記所含有的配送方式進行配送。
- `deliveryTemplateId` 運費模板id,根據不同的運費模板設計不同的配送費

運費模板的操作見 :運費模板的設計相關文章。
## 2.2 Sku
商品 SKU 。

```java
@Data
@TableName("tz_sku")
public class Sku implements Serializable {
/**
* 單品ID
*/
@TableId
private Long skuId;
/**
* 商品ID
*/
private Long prodId;
/**
* 銷售屬性組合字符串,格式是p1:v1;p2:v2
*/
private String properties;
/**
* 原價
*/
private Double oriPrice;
/**
* 價格
*/
private Double price;
/**
* 庫存
*/
private Integer stocks;
/**
* 實際庫存
*/
private Integer actualStocks;
/**
* 修改時間
*/
private Date updateTime;
/**
* 記錄時間
*/
private Date recTime;
/**
* 商家編碼
*/
private String partyCode;
/**
* 商品條形碼
*/
private String modelId;
/**
* sku圖片
*/
private String pic;
/**
* sku名稱
*/
private String skuName;
/**
* 商品名稱
*/
private String prodName;
/**
* 重量
*/
private Double weight;
/**
* 體積
*/
private Double volume;
/**
* 狀態:0禁用 1 啟用
*/
private Integer status;
/**
* 0 正常 1 已被刪除
*/
private Integer isDelete;
}
```
- `skuId` ,SKU 編號,自增,唯一,參見分銷場景。
- `prodId` ,商品編號,N:1 指向對應的 Product 。
- `status`,SKU 狀態。編輯商品時,當禁用該sku時,前端將會將該sku置灰
- `stocks` ,庫存數量。
- `properties`,商品規格,字符串拼接格式。
絕大多數情況下,數據庫里的該字段,不存在檢索的需求,更多的時候,是查詢整體記錄,在內存中解析使用。
少部分情況,靈活的檢索,使用 Elasticsearch 進行解決。
因為我們的規格是直接保存字符串的,所以可以選擇,或直接輸入

## 2.3 ProdProp
商品 SKU 規格屬性,在數據庫中保存的常用數據。不常用的數據可以直接手動輸入即可。

```java
public class ProdProp implements Serializable {
/**
* 屬性id
*/
@TableId
private Long propId;
/**
* 屬性名稱
*/
private String propName;
private Long shopId;
}
```
- `propId` ,屬性編號。
- `propName` ,屬性名稱。
## 2.4 ProdPropValue
商品 SKU 規格屬性,在數據庫中保存的常用數據。
```java
public class ProdProp implements Serializable {
/**
* 屬性值ID
*/
@TableId
private Long valueId;
/**
* 屬性值名稱
*/
private String propValue;
/**
* 屬性ID
*/
private Long propId;
}
```
- `valueId` ,屬性值ID。
- `propValue` ,屬性值名稱。
- 開發環境準備
- 基本開發手冊
- 項目目錄結構
- 權限管理
- 通用分頁表格
- Swagger文檔
- undertow容器
- 對xss攻擊的防御
- 分布式鎖
- 統一的系統日志
- 統一驗證
- 統一異常處理
- 文件上傳下載
- 一對多、多對多分頁
- 認證與授權
- 從授權開始看源碼
- 自己寫個授權的方法-開源版
- 商城表設計
- 商品信息
- 商品分組
- 購物車
- 訂單
- 地區管理
- 運費模板
- 接口設計
- 必讀
- 購物車的設計
- 訂單設計-確認訂單
- 訂單設計-提交訂單
- 訂單設計-支付
- 生產環境
- nginx安裝與跨域配置
- 安裝mysql
- 安裝redis
- 傳統方式部署項目
- docker
- 使用docker部署商城
- centos jdk安裝
- docker centos 安裝
- Docker Compose 安裝與卸載
- docker 鏡像的基本操作
- docker 容器的基本操作
- 通過yum安裝maven
- 常見問題