下载工作台
Go 数据库实战

毕业项目 shop-db 设计与验收

试读上半部分 · 解锁后可读全文

第 17 章 · 毕业项目 shop-db 设计与验收

本章目标:独立交付 shop-db Go 数据库毕业项目:完整 ER 图DDLgolang-migrate 迁移链GORM 实体seed;全链路贯彻 slug + is_published + price(分) 契约;按 100 分验收表自评;编写 docs/ 衔接 gin-web api-go-demo-demo 的 GORM 对照说明;形成可放入作品集的数据库设计文档。

学时建议:6~8 小时(含 4 小时建模与迁移)

前置:完成 ch01~ch16ch16 综合练习已通过;建议浏览 gin-web ch05 商品持久化章节。


17.1 项目背景与边界

shop-db 是虚构商城 贤紫优选Go 数据库层毕业交付,为 gin-web 毕业项目提供 唯一真相源(SSOT)

┌─────────────────────────────────────────────────────────┐
│                    shop-db(本章)                         │
│  ER · DDL · golang-migrate · GORM Entity · seed · docs           │
└───────────────────────────┬─────────────────────────────┘
                            │ 同 ER / 同字段契约
                            ▼
                   gin-web
                   api-go-demo-demo
                   Spring Data GORM + REST
模块shop-db 必须不做(扩展)
用户users 表 + slugOAuth 第三方表
商品products slug/is_published/price分SKU 矩阵多规格
分类categories 树形无限级性能优化
订单orders + order_items 快照分库分表落地
购物车cart_items分布式购物车
迁移golang-migrate 全链多 DB 联邦
严禁真实连接串、生产域名入库。统一 user-demoapi.example.com、本地 MySQL。

17.2 交付物清单

#交付物说明
1docs/ER.mdER 图(mermaid 或图片)+ 文字说明
2sql/schema.sql可独立执行的 DDL
3src/main/resources/db/migration/V*.sql≥2 个版本(初始 + 增量)
4src/main/go/.../catalog/*.goGORM 实体
5scripts/SeedMain.go 或 SQL seed样本数据
6docs/GORM_BRIDGE.mdgin-web 字段对照
7docs/SELF_REVIEW.md100 分自评表
8README.md安装、golang-migrate、seed 命令

17.3 推荐目录结构

~/go-learn/shop-db/
├── go.mod
├── sql/
│   └── schema.sql
├── src/main/go/com/zixian/shopdb/
│   ├── catalog/
│   │   ├── Category.go
│   │   ├── Product.go
│   │   └── ProductRepository.go
│   ├── order/
│   │   ├── ShopOrder.go
│   │   └── OrderItem.go
│   ├── user/
│   │   └── User.go
│   └── seed/
│       └── SeedMain.go
├── src/main/resources/
│   ├── META-INF/gorm.Open
│   └── db/migration/
│       ├── V1__initial_schema.sql
│       └── V2__add_product_view_count.sql
├── scripts/
│   └── run-flyway.sh
├── docs/
│   ├── ER.md
│   ├── GORM_BRIDGE.md
│   ├── SCALE.md          ← ch15 扩展预案
│   ├── PERF.md           ← ch14
│   └── SELF_REVIEW.md
└── README.md

17.4 ER 模型总览

17.4.1 实体关系(mermaid)

erDiagram
    users ||--o{ orders : places
    users ||--o{ cart_items : owns
    categories ||--o{ products : contains
    products ||--o{ cart_items : referenced
    orders ||--|{ order_items : contains
    products ||--o{ order_items : snapshot

    users {
        bigint id PK
        varchar slug UK
        varchar email UK
        varchar password_hash
        datetime created_at
    }
    categories {
        bigint id PK
        varchar slug UK
        varchar name
        bigint parent_id FK
    }
    products {
        bigint id PK
        varchar slug UK
        varchar name
        bigint price "分"
        bool is_published
        bigint category_id FK
        bigint view_count
    }
    orders {
        bigint id PK
        varchar order_no UK
        varchar user_slug
        varchar status
        bigint total_amount "分"
    }
    order_items {
        bigint id PK
        bigint order_id FK
        varchar product_slug
        bigint price "分"
        int quantity
    }
    cart_items {
        bigint id PK
        varchar user_slug
        bigint product_id FK
        int quantity
    }

17.4.2 设计原则

原则实现
价格全程 BIGINT 分
商品标识slug 对外;id 对内 FK
上下架is_published bool
订单快照order_items 冗余 slug/name/price
用户user_slug 便于与 JWT 对齐

17.5 完整 DDL(schema.sql 摘要)

CREATE DATABASE IF NOT EXISTS shop_db
  DEFAULT CHARACTER SET utf8mb4
  DEFAULT COLLATE utf8mb4_unicode_ci;

USE shop_db;

CREATE TABLE users (
    id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    slug VARCHAR(64) NOT NULL,
    email VARCHAR(255) NOT NULL,
    password_hash VARCHAR(255) NOT NULL,
    is_active TINYINT(1) NOT NULL DEFAULT 1,
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    UNIQUE KEY uk_users_slug (slug),
    UNIQUE KEY uk_users_email (email)
) ENGINE=InnoDB;

CREATE TABLE categories (
    id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    slug VARCHAR(128) NOT NULL,
    name VARCHAR(128) NOT NULL,
    parent_id BIGINT NULL,
    sort_order INT NOT NULL DEFAULT 0,
    UNIQUE KEY uk_categories_slug (slug),
    KEY idx_categories_parent (parent_id),
    CONSTRAINT fk_categories_parent FOREIGN KEY (parent_id) REFERENCES categories(id)
) ENGINE=InnoDB;

CREATE TABLE products (
    id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    slug VARCHAR(128) NOT NULL,
    name VARCHAR(256) NOT NULL,
    description TEXT NULL,
    price BIGINT NOT NULL COMMENT '价格-分',
    is_published TINYINT(1) NOT NULL DEFAULT 0,
    category_id BIGINT NULL,
    view_count BIGINT NOT NULL DEFAULT 0,
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    UNIQUE KEY uk_products_slug (slug),
    KEY idx_products_published_id (is_published, id DESC),
    KEY idx_products_category_published (category_id, is_published, id DESC),
    CONSTRAINT fk_products_category FOREIGN KEY (category_id) REFERENCES categories(id)
) ENGINE=InnoDB;

CREATE TABLE orders (
    id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    order_no VARCHAR(32) NOT NULL,
    user_slug VARCHAR(64) NOT NULL,
    status VARCHAR(16) NOT NULL DEFAULT 'pending',
    total_amount BIGINT NOT NULL COMMENT '订单总额-分',
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    UNIQUE KEY uk_orders_order_no (order_no),
    KEY idx_orders_user_created (user_slug, created_at DESC),
    KEY idx_orders_created (created_at)
) ENGINE=InnoDB;

CREATE TABLE order_items (
    id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    order_id BIGINT NOT NULL,
    product_id BIGINT NOT NULL,
    product_slug VARCHAR(128) NOT NULL,
    product_name VARCHAR(256) NOT NULL,
    price BIGINT NOT NULL COMMENT '成交单价-分',
    quantity INT NOT NULL,
    KEY idx_order_items_order (order_id),
    CONSTRAINT fk_order_items_order FOREIGN KEY (order_id) REFERENCES orders(id)
) ENGINE=InnoDB;

CREATE TABLE cart_items (
    id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    user_slug VARCHAR(64) NOT NULL,
    product_id BIGINT NOT NULL,
    quantity INT NOT NULL DEFAULT 1,
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    UNIQUE KEY uk_cart_user_product (user_slug, product_id),
    KEY idx_cart_user (user_slug),
    CONSTRAINT fk_cart_product FOREIGN KEY (product_id) REFERENCES products(id)
) ENGINE=InnoDB;

17.6 GORM 实体(Product 核心)

gorm.Model
@Table(name = "products")
public class Product {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false, unique = true, length = 128)
    private String slug;

    @Column(nullable = false, length = 256)
    private String name;

    @Column(nullable = false)
    private Long price; // 分

    @Column(name = "is_published", nullable = false)
    private boolean published;

    @Column(name = "category_id")
    private Long categoryId;

以下内容需解锁后阅读

试读已结束。解锁本章 ¥5.00,或开通年度会员畅读全部教程。
年度会员 ¥199.00/年; 小紫 AI 工作台有效会员 ¥99.00/年

正文仅在服务端鉴权后下发,未付费无法获取下半部分内容。