7--商品、活动、订单的Model实现
阶段回顾
User (已完成)
↓ JWT (已完成)
↓
商品/秒杀/订单 ← 当前阶段
↓
Redis 库存预热 ← 依赖 Seckill.Stock
↓
RabbitMQ 异步下单 ← 依赖 Order 创建
↓
秒杀接口 ← 需要 UserId 鉴权
想要完成秒杀,首先要确定哪个用户在抢,我们在先前通过JWT已经完成了用户身份验证逻辑
接下来要解决的就是在哪秒杀和秒杀什么,即秒杀活动和秒杀商品
而订单是秒杀的结果,用户抢购成功后生成Order,依赖 User、Product、Seckill 三个模型的外键关系
一. 模型设计
1) ER图
erDiagram
USER ||--o{ ORDER : "下单"
PRODUCT ||--o{ SECKILL : "举办活动"
PRODUCT ||--o{ ORDER : "包含"
SECKILL ||--o{ ORDER : "生成"
USER {
uint uid PK
string username
string email
string phone
string password
datetime created_at
}
PRODUCT {
uint product_id PK
string name
text description
decimal price
int stock
datetime created_at
}
SECKILL {
uint seckill_id PK
uint product_id FK
string name
decimal price
int stock
datetime start_time
datetime end_time
int status
datetime created_at
}
ORDER {
uint order_id PK
uint user_id FK
uint product_id FK
uint seckill_id FK
decimal amount
int status
datetime created_at
datetime updated_at
}
2) 秒杀状态机
graph LR
未开始[未开始<br>status=0] -->|开始| 进行中[进行中<br>status=1] -->|结束| 已结束[已结束<br>status=2]
3) 订单状态机
graph LR
待支付[待支付<br>status=0] -->|支付| 已支付[已支付<br>status=1]
已支付 -->|退款| 已退款[已退款<br>status=3]
待支付 -->|取消| 已取消[已取消<br>status=2]
4) 字段说明
| 模型 | 关键字段 | 作用 |
|---|---|---|
| Product | stock |
真实库存,秒杀前预热到 Redis |
| Seckill | stock, start_time, end_time, status |
控制秒杀活动的开始/结束/可用状态 |
| Order | user_id, seckill_id, amount, status |
关联用户、秒杀活动、金额、支付状态 |
二. 模型创建
三个go文件需要创建在internal/model/文件夹下
internal/model/
├── user.go # 已有
├── product.go # 新增
├── seckill.go # 新增
└── order.go # 新增
1) 商品模型
product.go
package model
import "time"
// Product 定义了商品的结构体,包含商品ID、名称、描述、价格、库存数量和创建时间等字段
type Product struct {
ProductId uint `gorm:"primaryKey;column:product_id;autoIncrement" json:"product_id"` // 商品ID,主键,自增
Name string `gorm:"column:name;type:varchar(100);not null" json:"name"` // 商品名称,字符串类型,最大长度100,不能为空
Description string `gorm:"column:description;type:text" json:"description"` // 商品描述,文本类型
Price float64 `gorm:"column:price;type:decimal(10,2);not null" json:"price"` // 商品价格,十进制类型,精度10位,小数点后2位,不能为空
Stock int `gorm:"column:stock;type:int;not null" json:"stock"` // 商品库存数量,整数类型,不能为空
CreatedAt time.Time `gorm:"column:created_at;autoCreateTime" json:"created_at"` // 商品创建时间,自动设置为当前时间
}
func (Product) TableName() string {
return "product" // 指定数据库表名为 "product"
}
2) 秒杀活动模型
seckill.go
package model
import "time"
// Seckill 定义了秒杀活动的结构体,包含秒杀活动ID、关联的商品ID、秒杀活动名称、库存数量、开始时间、结束时间、状态和创建时间等字段
type Seckill struct {
SeckillId uint `gorm:"primaryKey;column:seckill_id;autoIncrement" json:"seckill_id"` // 秒杀活动ID,主键,自增
ProductId uint `gorm:"column:product_id;not null" json:"product_id"` // 关联的商品ID,不能为空
Name string `gorm:"column:name;type:varchar(200);not null" json:"name"` // 秒杀活动名称,字符串类型,最大长度200,不能为空
Price float64 `gorm:"column:price;type:decimal(10,2);not null" json:"price"` // 秒杀价格,十进制类型,精度10位,小数点后2位,不能为空
Stock int `gorm:"column:stock;not null" json:"stock"` // 秒杀活动库存数量,不能为空
StartTime time.Time `gorm:"column:start_time;not null" json:"start_time"` // 秒杀活动开始时间,不能为空
EndTime time.Time `gorm:"column:end_time;not null" json:"end_time"` // 秒杀活动结束时间,不能为空
Status int `gorm:"column:status;type:int;default:0" json:"status"` // 秒杀活动状态,整数类型,不能为空
// (0:未开始,1:进行中,2:已结束)
CreatedAt time.Time `gorm:"column:created_at;autoCreateTime" json:"created_at"` // 秒杀活动创建时间,自动设置为当前时间
}
func (Seckill) TableName() string {
return "seckill" // 指定数据库表名为 "seckill"
}
3) 订单模型
order.go
package model
import "time"
// Order 定义了订单的结构体,包含订单ID、用户ID、商品ID、秒杀活动ID、订单金额、订单状态、创建时间和更新时间等字段
type Order struct {
OrderId uint `gorm:"primaryKey;column:order_id;autoIncrement" json:"order_id"` // 订单ID,主键,自增
UserId uint `gorm:"column:user_id;not null" json:"user_id"` // 关联的用户ID,不能为空
ProductId uint `gorm:"column:product_id;not null" json:"product_id"` // 关联的商品ID,不能为空
SeckillId uint `gorm:"column:seckill_id;not null" json:"seckill_id"` // 关联的秒杀活动ID,不能为空
Amount float64 `gorm:"column:amount;type:decimal(10,2);not null" json:"amount"` // 订单金额,十进制类型,精度10位,小数点后2位,不能为空
Status int `gorm:"column:status;type:int;default:0" json:"status"` // 订单状态,整数类型,不能为空
// (0:未支付,1:已支付,2:已取消)
CreatedAt time.Time `gorm:"column:created_at;autoCreateTime" json:"created_at"` // 订单创建时间,自动设置为当前时间
UpdatedAt time.Time `gorm:"column:updated_at;autoUpdateTime" json:"updated_at"` // 订单更新时间,自动设置为当前时间
}
func (Order) TableName() string {
return "order" // 指定数据库表名为 "order"
}
4) 数据库表关系
| 源实体 | 关系 | 目标实体 | 说明 |
|---|---|---|---|
| product(商品) | 一对多 | seckill(秒杀活动) | 一个商品可对应多个秒杀活动 |
| order(订单) | 一对一 | seckill(秒杀活动) | 一个用户 + 秒杀活动 = 一个订单 |
三. 更新AutoMigrate以便Gorm创建对应数据表
internal/repository/mysql.go
// InitMySQL 初始化数据库连接
func InitMySQL() {
// ... 其余代码 ...
// AutoMigrate 会根据 User 结构体自动创建或更新数据库表结构
if err := DB.AutoMigrate(&model.User{}, &model.Product{}, &model.Seckill{}, &model.Order{}); err != nil {
log.Fatalf("Failed to auto migrate tables: %v", err)
}
}
四. 运行
go run之后会发现数据库里自动创建了三个数据表,加上之前的User表一共是四个


浙公网安备 33010602011771号