petstore-docs/数据库设计规范.md

132 lines
4.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 宠伴生活馆 - 数据库设计规范
> 版本v1.0
> 日期2026-04-17
> 适用范围后端Spring Boot + JPA + MySQL、与数据模型相关的产品说明
**相关文档:**
- [产品设计文档](./产品设计文档.md) — 业务数据模型总览
- [前端 UI 规范](./前端UI规范.md) — 与展示无关,仅作项目索引
---
## 1. 目标
- 表结构可读、可演进,多人协作时不靠口头约定。
- 与 Java 实体、JPA 映射一致,减少「库里有、代码里没有」的漂移。
- 业务删除以**逻辑删除**为主,保留审计与恢复空间。
---
## 2. 技术前提
| 项 | 约定 |
|----|------|
| 数据库 | MySQL 8.x建议 `utf8mb4` / `utf8mb4_unicode_ci` |
| ORM | Spring Data JPAHibernate |
| 时区 | 连接串带 `serverTimezone=Asia/Shanghai`,应用侧统一东八区语义 |
| 结构演进 | 开发环境可用 `spring.jpa.hibernate.ddl-auto=update`**生产环境建议改为 `validate``none`,配合显式迁移脚本** |
---
## 3. 命名规范
### 3.1 表名
- 使用**小写 + 下划线**,业务表统一加前缀 **`t_`**。
示例:`t_user`、`t_store`、`t_appointment`、`t_report`、`t_pet`。
- 关联表、中间表同样遵循:`t_xxx_yyy` 或业务可读缩写。
### 3.2 字段名
- 数据库列:**snake_case**`user_id`、`create_time`)。
- Java 实体:**camelCase**,通过 `@Column(name = "xxx")` 与列名对齐。
- 外键含义字段统一命名为 `xxx_id`(如 `store_id`、`user_id`、`pet_id`)。
### 3.3 避免保留字与模糊命名
- 避免单独使用 `order`、`group`、`status` 等易冲突名时,在业务上可加前缀或放在明确表上下文中;若已使用,保持全项目一致即可。
---
## 4. 主键与类型
| 类型 | 约定 |
|------|------|
| 主键 | `BIGINT` 自增JPA 使用 `@GeneratedValue(strategy = GenerationType.IDENTITY)` |
| 金额 | 若后续涉及订单金额,优先用**分**整型或 `DECIMAL`,不以 `DOUBLE` 存金额 |
| 布尔 | MySQL 用 `TINYINT(1)`JPA 用 `Boolean`,必要时 `columnDefinition = "TINYINT(1) DEFAULT 0"` 与库一致 |
| 文本 | 短字符串 `VARCHAR`;长描述、备注可用 `TEXT`(以实体为准) |
---
## 5. 时间字段
- **`create_time`**:创建时间,插入时赋值,一般不在业务修改流程中更新。
- **`update_time`**:最后更新时间,任意业务更新时刷新。
- Java 类型统一 **`LocalDateTime`**。
- 不在数据库层用 `ON UPDATE CURRENT_TIMESTAMP` 替代应用赋值,除非团队明确约定(当前项目以应用赋值为主)。
---
## 6. 逻辑删除(软删除)
### 6.1 字段约定
- 列名:**`deleted`**
- 含义:`0` / `false` 表示未删除,`1` / `true` 表示已删除。
- 新建行必须为未删除;应用层 `save` 时显式 `setDeleted(false)`,避免空值歧义。
### 6.2 使用范围(本项目)
以下核心业务实体已统一带逻辑删除,**列表与详情查询默认只包含 `deleted = false` 的记录**
- 门店 `t_store`
- 用户 `t_user`
- 宠物 `t_pet`
- 预约 `t_appointment`
- 报告 `t_report`
### 6.3 业务规则
- **禁止**在业务 Service 中对上述实体使用物理 `deleteById`(除非运维级清理且走专门流程)。
- 删除操作:**将 `deleted` 置为 `true`,并更新 `update_time`**。
- 所有自定义查询JPQL / 原生 SQL必须显式带上 `deleted` 条件,避免漏过滤。
- 唯一性约束(如手机号唯一)若与软删除并存,需在业务或迁移层设计「仅对未删除行唯一」或预留恢复策略;新增表时提前评审。
### 6.4 后续扩展(可选)
- **回收站 / 恢复**:将 `deleted` 改回 `false` 并刷新 `update_time`
- **删除人 / 删除时间**:若审计要求提高,可增加 `deleted_at`、`deleted_by`(非当前必选项)。
---
## 7. 索引
- 外键及高频筛选字段建立索引:如 `user_id`、`store_id`、`status`、时间排序字段等。
- 联合索引遵循**最左前缀**:查询条件里经常一起出现的列再组合(如 `store_id + status + appointment_time`)。
- 命名建议:`idx_<表简写>_<字段简写>`,与实体 `@Index` 保持一致,便于对照。
---
## 8. 冗余字段
- 允许在**读多写少、展示为主**的表做冗余(如报告中的宠物名、服务类型、预约时间、技师名),以减少联表。
- 冗余字段须在注释或设计文档中标明「来源表 + 字段」,变更来源数据时评估是否同步更新(或由业务流程保证一次性写入)。
---
## 9. 与代码的同步
- 新增/变更列:先改 **实体类**,再让迁移或 `ddl-auto` 落库,避免手写库结构与实体不一致。
- Code Review 检查点:字段名、是否逻辑删除、索引是否与查询一致。
---
## 10. 修订记录
| 版本 | 日期 | 说明 |
|------|------|------|
| v1.0 | 2026-04-17 | 初稿:命名、时间、逻辑删除、索引、冗余字段 |