数据库设计 - 核心系统 (Release 1)#
本文档描述平台核心功能的数据库设计,包括用户、课程、章节、任务、进度追踪和课程报名。
Release 2 道馆系统: 参见 数据库设计 - 道馆系统
ER 图#
erDiagram
User ||--o{ MissionProgress : has
User ||--o{ CourseEnrollment : has
User ||--o{ UserSkill : has
Course ||--o{ Chapter : contains
Course ||--o{ CourseEnrollment : enrolled_by
Chapter ||--o{ Mission : contains
Chapter ||--o{ Gym : contains
Mission ||--o{ MissionProgress : tracked_by
User {
bigint id PK
string email UK
string password
string name
string auth_provider "LOCAL/GOOGLE"
string google_id
string role "STUDENT/TEACHER"
int level
int exp
string title
string avatar_url
string nickname
string gender
string profession
date birthday
string region
string github_url
timestamp created_at
timestamp updated_at
}
Course {
bigint id PK
string name
text description
string image_url
decimal price
string level
string instructor
int total_duration
int student_count
string category
boolean has_free_preview
}
Chapter {
bigint id PK
bigint course_id FK
string title
int order_index
}
Mission {
bigint id PK
bigint chapter_id FK
string title
string type "VIDEO/ARTICLE/SURVEY"
text content
string video_url
int exp_reward
int order_index
boolean is_free_preview
}
MissionProgress {
bigint id PK
bigint user_id FK
bigint mission_id FK
int progress
boolean completed
boolean reward_claimed
int last_watched_position
int video_duration
int watched_time
timestamp completed_at
timestamp updated_at
}
CourseEnrollment {
bigint id PK
bigint user_id FK
bigint course_id FK
string type "FREE/PURCHASED/GIFTED"
string status "PENDING/COMPLETED/CANCELLED"
timestamp enrolled_at
timestamp completed_at
}
Gym {
bigint id PK
bigint chapter_id FK
string name
string category
string difficulty
}注意: Gym 及其相关实体的完整定义参见 数据库设计 - 道馆系统
表结构#
users 表#
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | BIGINT | PK, AUTO_INCREMENT | 用户 ID |
| VARCHAR(255) | UNIQUE, NOT NULL | 邮箱 | |
| password | VARCHAR(255) | 加密密码(OAuth 用户可为空) | |
| name | VARCHAR(100) | NOT NULL | 用户名 |
| auth_provider | VARCHAR(20) | NOT NULL, DEFAULT ‘LOCAL’ | 认证方式 (LOCAL/GOOGLE) |
| google_id | VARCHAR(255) | Google OAuth ID | |
| role | VARCHAR(20) | NOT NULL, DEFAULT ‘STUDENT’ | 角色 (STUDENT/TEACHER) |
| level | INT | DEFAULT 1 | 等级 (1-36) |
| exp | INT | DEFAULT 0 | 经验值 |
| title | VARCHAR(50) | DEFAULT ‘初級工程師’ | 称号 |
| avatar_url | VARCHAR(500) | 头像 URL | |
| nickname | VARCHAR(100) | 昵称 | |
| gender | VARCHAR(20) | 性别 | |
| profession | VARCHAR(100) | 职业 | |
| birthday | DATE | 生日 | |
| region | VARCHAR(100) | 地区 | |
| github_url | VARCHAR(500) | GitHub URL | |
| created_at | TIMESTAMP | NOT NULL, DEFAULT NOW() | 创建时间 |
| updated_at | TIMESTAMP | 更新时间 |
索引:
- PRIMARY KEY (id)
- UNIQUE INDEX (email)
- INDEX (google_id)
courses 表#
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | BIGINT | PK, AUTO_INCREMENT | 课程 ID |
| name | VARCHAR(200) | NOT NULL | 课程名称 |
| description | TEXT | 课程描述 | |
| image_url | VARCHAR(500) | 封面图 | |
| price | DECIMAL(10,2) | 价格 | |
| level | VARCHAR(50) | 难度等级 | |
| instructor | VARCHAR(100) | 讲师 | |
| total_duration | INT | 总时长(秒) | |
| student_count | INT | DEFAULT 0 | 学生数 |
| category | VARCHAR(100) | 课程分类 | |
| has_free_preview | BOOLEAN | DEFAULT true | 是否有免费预览 |
关联表:
course_features(ElementCollection): 存储课程启用的功能列表
chapters 表#
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | BIGINT | PK, AUTO_INCREMENT | 章节 ID |
| course_id | BIGINT | FK, NOT NULL | 课程 ID |
| title | VARCHAR(200) | NOT NULL | 章节标题 |
| order_index | INT | NOT NULL | 排序索引 |
外键:
- FOREIGN KEY (course_id) REFERENCES courses(id) ON DELETE CASCADE
说明:
- 每个章节可包含多个任务 (missions) 和多个道馆 (gyms)
- 道馆系统详见 数据库设计 - 道馆系统
missions 表#
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | BIGINT | PK, AUTO_INCREMENT | 任务 ID |
| chapter_id | BIGINT | FK, NOT NULL | 章节 ID |
| title | VARCHAR(200) | NOT NULL | 任务标题 |
| type | VARCHAR(20) | NOT NULL | 类型 (VIDEO/ARTICLE/SURVEY) |
| content | TEXT | 文章内容 | |
| video_url | VARCHAR(500) | 视频 URL | |
| exp_reward | INT | DEFAULT 100 | 经验值奖励 |
| order_index | INT | 排序索引 | |
| is_free_preview | BOOLEAN | DEFAULT false | 是否免费预览 |
外键:
- FOREIGN KEY (chapter_id) REFERENCES chapters(id) ON DELETE CASCADE
mission_progress 表#
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | BIGINT | PK, AUTO_INCREMENT | 进度 ID |
| user_id | BIGINT | FK, NOT NULL | 用户 ID |
| mission_id | BIGINT | FK, NOT NULL | 任务 ID |
| progress | INT | DEFAULT 0 | 完成百分比 (0-100) |
| completed | BOOLEAN | DEFAULT false | 是否已完成 |
| reward_claimed | BOOLEAN | DEFAULT false | 是否已领奖 |
| last_watched_position | INT | DEFAULT 0 | 最后观看位置(秒) |
| video_duration | INT | 视频总时长(秒) | |
| watched_time | INT | DEFAULT 0 | 累积观看时间(秒,防作弊用) |
| completed_at | TIMESTAMP | 完成时间 | |
| updated_at | TIMESTAMP | 更新时间 |
索引:
- UNIQUE INDEX (user_id, mission_id)
- FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
- FOREIGN KEY (mission_id) REFERENCES missions(id) ON DELETE CASCADE
course_enrollments 表#
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | BIGINT | PK, AUTO_INCREMENT | 报名 ID |
| user_id | BIGINT | FK, NOT NULL | 用户 ID |
| course_id | BIGINT | FK, NOT NULL | 课程 ID |
| type | VARCHAR(20) | NOT NULL, DEFAULT ‘PURCHASED’ | 报名类型 (FREE/PURCHASED/GIFTED) |
| status | VARCHAR(20) | NOT NULL, DEFAULT ‘PENDING’ | 支付状态 (PENDING/COMPLETED/CANCELLED) |
| enrolled_at | TIMESTAMP | NOT NULL, DEFAULT NOW() | 报名时间 |
| completed_at | TIMESTAMP | 完成时间 |
索引:
- UNIQUE INDEX (user_id, course_id)
- FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
- FOREIGN KEY (course_id) REFERENCES courses(id) ON DELETE CASCADE
数据库优化#
索引策略#
- 主键索引: 所有表都有自增主键
- 唯一索引:
- users.email
- (user_id, mission_id) 组合
- (user_id, course_id) 组合
- 外键索引: 自动创建
查询优化#
-- 高效查询用户排行榜(已建立索引)
SELECT id, name, level, exp, title, avatar_url
FROM users
ORDER BY exp DESC
LIMIT 100;
-- 高效查询用户进度(组合索引)
SELECT mp.*
FROM mission_progress mp
WHERE mp.user_id = ? AND mp.mission_id = ?;
-- 课程详情(使用 JOIN 优化)
SELECT c.*, ch.*, m.*
FROM courses c
LEFT JOIN chapters ch ON ch.course_id = c.id
LEFT JOIN missions m ON m.chapter_id = ch.id
WHERE c.id = ?
ORDER BY ch.order_index, m.id;数据初始化#
系统启动时自动初始化种子数据(参见 DataInitializer.java)。