Skip to content

数据库设计规范

1. 表设计规范

1.1 基础表结构

梵医云项目采用统一的表结构设计,所有业务表应继承基础字段。

sql
-- ✅ 符合规范的表设计
CREATE TABLE `system_users` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '用户ID',
  `username` varchar(50) NOT NULL COMMENT '用户账号',
  `password` varchar(100) NOT NULL COMMENT '加密后的密码',
  `nickname` varchar(50) DEFAULT NULL COMMENT '用户昵称',
  `remark` varchar(500) DEFAULT NULL COMMENT '备注',
  `dept_id` bigint DEFAULT NULL COMMENT '部门ID',
  `post_ids` json DEFAULT NULL COMMENT '岗位编号数组',
  `email` varchar(50) DEFAULT NULL COMMENT '用户邮箱',
  `mobile` varchar(11) DEFAULT NULL COMMENT '手机号码',
  `sex` tinyint DEFAULT NULL COMMENT '用户性别',
  `avatar` varchar(512) DEFAULT NULL COMMENT '用户头像',
  `status` tinyint NOT NULL DEFAULT '0' COMMENT '帐号状态',
  `login_ip` varchar(50) DEFAULT NULL COMMENT '最后登录IP',
  `login_date` datetime DEFAULT NULL COMMENT '最后登录时间',
  `tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号',
  `creator` varchar(64) DEFAULT '' COMMENT '创建者',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `updater` varchar(64) DEFAULT '' COMMENT '更新者',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_username` (`username`),
  KEY `idx_dept_id` (`dept_id`),
  KEY `idx_mobile` (`mobile`),
  KEY `idx_status` (`status`),
  KEY `idx_create_time` (`create_time`),
  KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB 
  DEFAULT CHARSET=utf8mb4 
  COLLATE=utf8mb4_unicode_ci 
  COMMENT='管理后台的用户'
  ROW_FORMAT=DYNAMIC;

1.2 基础字段说明

所有业务表必须包含以下基础字段:

字段名类型说明必填默认值
idbigint主键IDAUTO_INCREMENT
tenant_idbigint租户编号0
creatorvarchar(64)创建者''
create_timedatetime创建时间CURRENT_TIMESTAMP
updatervarchar(64)更新者''
update_timedatetime更新时间CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
deletedbit(1)是否删除b'0'

1.3 表命名规范

规则说明示例
模块前缀表名以模块名开头system_users, infra_config
下划线分隔使用下划线分隔单词user_role, dept_post
复数形式实体表使用复数形式users, roles
关系表使用下划线连接两个表名user_role, role_menu

示例

  • system_users - 系统用户表
  • system_dept - 系统部门表
  • system_user_role - 用户角色关联表
  • infra_config - 基础设施配置表
  • infra_api_access_log - API访问日志表

2. 字段设计规范

2.1 字段命名规范

规则说明示例
小写字母全部使用小写字母username, email
下划线分隔多个单词使用下划线分隔user_name, create_time
布尔字段以is_开头is_deleted, is_active
时间字段以_time结尾create_time, login_time
日期字段以_date结尾birth_date, login_date
ID字段以_id结尾user_id, dept_id
类型字段以_type结尾user_type, status_type
状态字段以status结尾status, login_status

2.2 字段类型规范

数据类型使用场景长度/精度示例
bigint主键、外键ID20id, user_id, dept_id
int状态、类型、数量11status, type, sort
tinyint布尔值、小范围枚举1deleted, sex
decimal金额、精确数值(10,2)price, amount
varchar(n)变长字符串根据实际需求username(50), email(100)
char(n)定长字符串根据实际需求code(32)
text长文本65535content, description
datetime日期时间-create_time, update_time
timestamp时间戳-login_time
jsonJSON数据-post_ids, extra_info
blob二进制数据-file_data

2.3 字段注释规范

所有字段必须添加注释,注释应清晰描述字段含义。

sql
-- ✅ 正确的字段注释
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '用户ID',
`username` varchar(50) NOT NULL COMMENT '用户账号',
`password` varchar(100) NOT NULL COMMENT '加密后的密码',
`status` tinyint NOT NULL DEFAULT '0' COMMENT '帐号状态(0正常 1停用)',

-- ❌ 错误的字段注释
`id` bigint NOT NULL AUTO_INCREMENT COMMENT 'ID',
`username` varchar(50) NOT NULL COMMENT '名字',
`status` tinyint NOT NULL DEFAULT '0' COMMENT '状态',

2.4 特殊字段类型处理

2.4.1 JSON字段

对于数组或复杂对象,使用JSON类型存储:

sql
-- 存储岗位ID数组
`post_ids` json DEFAULT NULL COMMENT '岗位编号数组',

-- 存储扩展信息
`extra_info` json DEFAULT NULL COMMENT '扩展信息',

在Java代码中使用 @TableField(typeHandler = JacksonTypeHandler.class) 注解处理:

java
@TableField(typeHandler = JacksonTypeHandler.class)
private Set<Long> postIds;

2.4.2 布尔字段

使用 bit(1) 类型存储布尔值:

sql
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`visible` bit(1) NOT NULL DEFAULT b'1' COMMENT '是否可见',

在Java代码中使用 Boolean 类型:

java
@TableLogic
private Boolean deleted;

2.4.3 金额字段

使用 decimal 类型存储金额,避免精度丢失:

sql
`price` decimal(10,2) DEFAULT NULL COMMENT '价格',
`amount` decimal(12,2) DEFAULT NULL COMMENT '金额',

在Java代码中使用 BigDecimal 类型:

java
private BigDecimal price;
private BigDecimal amount;

3. 索引设计规范

3.1 索引命名规范

索引类型命名规则示例
主键索引PRIMARYPRIMARY KEY (id)
唯一索引uk_字段名UNIQUE KEY uk_username (username)
普通索引idx_字段名KEY idx_dept_id (dept_id)
联合索引idx_字段1_字段2KEY idx_user_type_status (user_type, status)

3.2 索引设计原则

sql
-- ✅ 正确的索引使用

-- 1. 主键自动创建索引
PRIMARY KEY (`id`)

-- 2. 唯一约束使用UNIQUE KEY
UNIQUE KEY `uk_username` (`username`)
UNIQUE KEY `uk_email` (`email`)

-- 3. 查询条件字段建立索引
KEY `idx_dept_id` (`dept_id`)
KEY `idx_status` (`status`)

-- 4. 联合索引注意顺序(最左前缀原则)
KEY `idx_user_type_status` (`user_type`, `status`)

-- 5. 时间字段建立索引(用于范围查询)
KEY `idx_create_time` (`create_time`)

-- 6. 外键字段建立索引
KEY `idx_tenant_id` (`tenant_id`)

-- ❌ 禁止的操作

-- 1. 禁止在WHERE条件中使用的字段不建索引
-- 2. 禁止在频繁更新的字段上建过多索引
-- 3. 禁止在区分度低的字段上建索引(如性别)
-- 4. 禁止索引数量超过表字段数的30%
-- 5. 禁止在LIKE '%xxx'查询的字段上建索引

3.3 索引使用建议

场景建议示例
主键查询自动索引WHERE id = 1
唯一性查询唯一索引WHERE username = 'admin'
范围查询普通索引WHERE create_time > '2024-01-01'
排序查询联合索引ORDER BY create_time DESC
多条件查询联合索引WHERE type = 1 AND status = 0
模糊查询前缀索引WHERE username LIKE 'admin%'

4. 约束设计规范

4.1 主键约束

所有表必须有主键,推荐使用自增ID:

sql
PRIMARY KEY (`id`)

对于Oracle、PostgreSQL等数据库,使用序列:

sql
@KeySequence("system_users_seq")

4.2 唯一约束

对于需要唯一性的字段,使用唯一约束:

sql
UNIQUE KEY `uk_username` (`username`),
UNIQUE KEY `uk_email` (`email`),
UNIQUE KEY `uk_mobile` (`mobile`),

4.3 非空约束

对于必填字段,设置NOT NULL:

sql
`username` varchar(50) NOT NULL COMMENT '用户账号',
`status` tinyint NOT NULL DEFAULT '0' COMMENT '帐号状态',

4.4 默认值

为字段设置合理的默认值:

sql
`status` tinyint NOT NULL DEFAULT '0' COMMENT '帐号状态',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',

4.5 外键约束

项目不使用外键约束,通过应用层维护数据一致性:

sql
-- ❌ 不推荐使用外键约束
-- FOREIGN KEY (dept_id) REFERENCES system_dept(id)

-- ✅ 推荐通过应用层维护
-- 在Service层进行数据校验

5. Java实体类映射规范

5.1 基础实体类

所有实体类应继承 TenantBaseDOBaseDO

java
@TableName(value = "system_users", autoResultMap = true)
@KeySequence("system_users_seq")
@Data
@EqualsAndHashCode(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class AdminUserDO extends TenantBaseDO {

    @TableId
    private Long id;
    
    private String username;
    
    private String password;
    
    private String nickname;
    
    // ... 其他字段
}

5.2 注解使用规范

注解用途示例
@TableName指定表名@TableName("system_users")
@TableId标记主键@TableId
@KeySequence指定序列@KeySequence("system_users_seq")
@TableField标记字段@TableField("user_name")
@TableLogic逻辑删除@TableLogic
@TableField(typeHandler)类型处理器@TableField(typeHandler = JacksonTypeHandler.class)
@TableField(exist = false)非数据库字段@TableField(exist = false)

5.3 基础字段映射

java
// BaseDO 基类包含以下字段:
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;

@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;

@TableField(fill = FieldFill.INSERT, jdbcType = JdbcType.VARCHAR)
private String creator;

@TableField(fill = FieldFill.INSERT_UPDATE, jdbcType = JdbcType.VARCHAR)
private String updater;

@TableLogic
private Boolean deleted;

// TenantBaseDO 基类额外包含:
private Long tenantId;

6. 数据库引擎规范

6.1 存储引擎

所有表使用 InnoDB 存储引擎:

sql
ENGINE=InnoDB

6.2 字符集

使用 utf8mb4 字符集,支持存储emoji等特殊字符:

sql
DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_unicode_ci

6.3 行格式

使用 DYNAMIC 行格式:

sql
ROW_FORMAT=DYNAMIC

7. 表设计示例

7.1 单表示例

sql
CREATE TABLE `system_dept` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '部门ID',
  `name` varchar(50) NOT NULL COMMENT '部门名称',
  `parent_id` bigint NOT NULL DEFAULT '0' COMMENT '父部门ID',
  `sort` int NOT NULL DEFAULT '0' COMMENT '显示顺序',
  `leader_user_id` bigint DEFAULT NULL COMMENT '负责人',
  `phone` varchar(11) DEFAULT NULL COMMENT '联系电话',
  `email` varchar(50) DEFAULT NULL COMMENT '邮箱',
  `status` tinyint NOT NULL DEFAULT '0' COMMENT '部门状态',
  `tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号',
  `creator` varchar(64) DEFAULT '' COMMENT '创建者',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `updater` varchar(64) DEFAULT '' COMMENT '更新者',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
  PRIMARY KEY (`id`),
  KEY `idx_parent_id` (`parent_id`),
  KEY `idx_status` (`status`),
  KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB 
  DEFAULT CHARSET=utf8mb4 
  COLLATE=utf8mb4_unicode_ci 
  COMMENT='部门表'
  ROW_FORMAT=DYNAMIC;

7.2 关系表示例

sql
CREATE TABLE `system_user_role` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增编号',
  `user_id` bigint NOT NULL COMMENT '用户ID',
  `role_id` bigint NOT NULL COMMENT '角色ID',
  `type` tinyint NOT NULL DEFAULT '1' COMMENT '角色类型',
  `tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号',
  `creator` varchar(64) DEFAULT '' COMMENT '创建者',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `updater` varchar(64) DEFAULT '' COMMENT '更新者',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_user_role` (`user_id`, `role_id`),
  KEY `idx_role_id` (`role_id`),
  KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB 
  DEFAULT CHARSET=utf8mb4 
  COLLATE=utf8mb4_unicode_ci 
  COMMENT='用户和角色关联表'
  ROW_FORMAT=DYNAMIC;

7.3 树形表示例

sql
CREATE TABLE `system_menu` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '菜单ID',
  `name` varchar(50) NOT NULL COMMENT '菜单名称',
  `permission` varchar(100) DEFAULT NULL COMMENT '权限标识',
  `type` tinyint NOT NULL COMMENT '菜单类型',
  `sort` int NOT NULL DEFAULT '0' COMMENT '显示顺序',
  `parent_id` bigint NOT NULL DEFAULT '0' COMMENT '父菜单ID',
  `path` varchar(200) DEFAULT '' COMMENT '路由地址',
  `icon` varchar(100) DEFAULT '#' COMMENT '菜单图标',
  `component` varchar(255) DEFAULT NULL COMMENT '组件路径',
  `component_name` varchar(255) DEFAULT NULL COMMENT '组件名',
  `status` tinyint NOT NULL DEFAULT '0' COMMENT '菜单状态',
  `visible` bit(1) NOT NULL DEFAULT b'1' COMMENT '是否可见',
  `keep_alive` bit(1) NOT NULL DEFAULT b'1' COMMENT '是否缓存',
  `always_show` bit(1) NOT NULL DEFAULT b'1' COMMENT '是否总是显示',
  `tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号',
  `creator` varchar(64) DEFAULT '' COMMENT '创建者',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `updater` varchar(64) DEFAULT '' COMMENT '更新者',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
  PRIMARY KEY (`id`),
  KEY `idx_parent_id` (`parent_id`),
  KEY `idx_status` (`status`),
  KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB 
  DEFAULT CHARSET=utf8mb4 
  COLLATE=utf8mb4_unicode_ci 
  COMMENT='菜单权限表'
  ROW_FORMAT=DYNAMIC;

8. 数据库设计最佳实践

8.1 设计原则

  1. 遵循第三范式:消除传递依赖,减少数据冗余
  2. 适当反范式:为了性能考虑,可以适当冗余字段
  3. 字段最少化:只包含必要的字段,避免过度设计
  4. 命名一致性:保持命名风格的一致性
  5. 注释完整:为所有表和字段添加清晰的注释

8.2 性能优化

  1. 合理使用索引:为查询条件、排序字段建立索引
  2. 避免大表:单表数据量建议不超过1000万
  3. 分表分库:对于大表考虑分表分库策略
  4. 使用缓存:对于热点数据使用Redis缓存
  5. 避免全表扫描:查询条件尽量使用索引字段

8.3 安全规范

  1. 敏感字段加密:密码、手机号等敏感字段加密存储
  2. 逻辑删除:使用deleted字段标记删除,不物理删除
  3. 多租户隔离:通过tenant_id实现数据隔离
  4. 权限控制:在应用层实现数据权限控制

9. 常见问题

9.1 如何处理多租户?

所有业务表添加 tenant_id 字段,实体类继承 TenantBaseDO

sql
`tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号',
KEY `idx_tenant_id` (`tenant_id`)
java
public class AdminUserDO extends TenantBaseDO {
    // tenant_id 字段自动继承
}

9.2 如何实现逻辑删除?

使用 deleted 字段标记删除状态:

sql
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
java
@TableLogic
private Boolean deleted;

9.3 如何存储数组或复杂对象?

使用 JSON 类型存储:

sql
`post_ids` json DEFAULT NULL COMMENT '岗位编号数组',
java
@TableField(typeHandler = JacksonTypeHandler.class)
private Set<Long> postIds;

9.4 如何处理金额字段?

使用 decimal 类型,避免精度丢失:

sql
`price` decimal(10,2) DEFAULT NULL COMMENT '价格',
java
private BigDecimal price;

注意:本文档持续更新中,如有问题请及时反馈。