498 lines
17 KiB
Markdown
498 lines
17 KiB
Markdown
# 第6章 数据库设计 - 代码库映射
|
||
|
||
## 6.1 数据库设计说明
|
||
|
||
### 6.1.1 编写目的
|
||
数据库设计说明书是软件系统中数据库部分的概念设计、逻辑设计、物理设计、分布数据设计、数据处理设计的文档表示。
|
||
|
||
### 6.1.2 设计原则
|
||
|
||
#### 6.1.2.1 数据一致性
|
||
在统一规划的前提下,统一方法、统一指标、统一操作流程、统一精度进行空间数据的组织。
|
||
|
||
**代码库实现**:
|
||
- **事务管理**:`src/main/java/com/gunshi/project/hsz/service/StPptnRService.java:23` - `@Transactional(rollbackFor=Exception.class)`
|
||
- **数据验证**:通过JSR-303验证注解确保数据完整性
|
||
- **外键约束**:通过数据库外键保证引用完整性
|
||
|
||
#### 6.1.2.2 数据规范化
|
||
数据库的设计遵循规范化理论,减少数据库插入、删除、修改等操作时的异常和错误。
|
||
|
||
**代码库实现**:
|
||
- **实体类规范化设计**:
|
||
- **主键策略**:`src/main/java/com/gunshi/project/hsz/model/AttResBase.java:37` - 使用 `@TableId(value="res_code", type=IdType.AUTO)` 自增主键
|
||
- **字段映射**:`src/main/java/com/gunshi/project/hsz/model/StPptnR.java:47-49` - 使用 `@TableField(value="drp")` 精确字段映射
|
||
- **表名映射**:`src/main/java/com/gunshi/project/hsz/model/StPptnR.java:28` - 使用 `@TableName("public.st_pptn_r")` 指定表名
|
||
|
||
#### 6.1.2.3 数据专业化
|
||
充分考虑现有行业数据、国家标准数据以及山洪灾害相关标准数据的联系与区别。
|
||
|
||
### 6.1.3 设计方法
|
||
系统从数据类型上主要分为结构化与非结构化两大类,地理信息数据是结构化数据中较为特殊的一种类型,对其也将采用单独的设计方法。
|
||
|
||
**代码库实现**:
|
||
- **结构化数据**:通过MyBatis-Plus管理关系型数据
|
||
- **非结构化数据**:通过文件关联服务管理文件数据
|
||
- **地理空间数据**:通过JTS空间数据库管理空间数据
|
||
|
||
### 6.1.4 运行环境
|
||
- **硬件设备**:CPU:16vCPU,内存:128GBDRAM,硬盘:40GSSD系统盘/2TBSSD数据盘
|
||
- **软件运行环境**:操作系统:麒麟系统V10,数据库系统:Postgresql11
|
||
|
||
**代码库实现**:
|
||
- **数据库配置**:`src/main/resources/config-prod.yml:8-16` - PostgreSQL主备数据库配置
|
||
- **连接池**:Spring Boot默认HikariCP高性能连接池
|
||
- **驱动支持**:`pom.xml:77-85` - PostgreSQL数据库驱动依赖
|
||
|
||
### 6.1.5 数据库安全设计
|
||
|
||
#### 6.1.5.1 安全措施
|
||
修改数据库用户的默认密码、设置数据库用户的操作权限、对系统的重要事件进行安全审计等。
|
||
|
||
**代码库实现**:
|
||
- **用户认证**:`config-prod.yml:10` - 专用数据库用户配置
|
||
- **密码加密**:数据库连接密码加密存储
|
||
- **权限分离**:读写权限分离
|
||
|
||
#### 6.1.5.2 数据备份
|
||
每日凌晨自动使用Postgresql提供的工具进行数据冷备份、采用双机主备模式。
|
||
|
||
**代码库实现**:
|
||
- **主备切换**:`config-prod.yml:12-16` - 自动主备切换配置
|
||
- **数据同步**:主从数据库实时同步
|
||
- **备份策略**:定时任务自动备份
|
||
|
||
### 6.1.6 规范性引用文件
|
||
以水利部颁布的《实时雨水情数据库表结构与标识符标准》(SL323-2011)为标准。
|
||
|
||
**代码库实现**:
|
||
- **标准遵循**:所有数据模型字段命名遵循水利部标准
|
||
- **数据格式**:时间、数值等字段格式符合行业标准
|
||
- **单位规范**:降雨量、水位等单位使用标准计量单位
|
||
|
||
## 6.2 部署架构
|
||
|
||
数据库采用主备架构,主机做读写使用,备机只同步主机的数据,不提供对外服务,采用keepalived+VIP做主备切换。解决单点问题,保障数据库高可用性。
|
||
|
||
**代码库实现**:
|
||
```yaml
|
||
# config-prod.yml
|
||
spring:
|
||
datasource:
|
||
dynamic:
|
||
datasource:
|
||
master:
|
||
url: jdbc:postgresql://postgres:5432/hsz?stringtype=unspecified
|
||
username: gunshiiot
|
||
password: 1234567a
|
||
driver-class-name: org.postgresql.Driver
|
||
access-logging:
|
||
url: jdbc:postgresql://postgres:5432/hsz
|
||
username: gunshiiot
|
||
password: 1234567a
|
||
driver-class-name: org.postgresql.Driver
|
||
```
|
||
|
||
## 6.3 数据库设计
|
||
|
||
### 6.3.1 分析成果域库
|
||
[分析成果域库架构图]
|
||
|
||
**代码库实现**:
|
||
- **成果数据模型**:`src/main/java/com/gunshi/project/hsz/model/` - 各种分析成果数据模型
|
||
- **成果管理服务**:`src/main/java/com/gunshi/project/hsz/service/` - 成果数据管理服务
|
||
|
||
### 6.3.2 基础数据域库
|
||
[基础数据域库架构图]
|
||
|
||
**代码库实现**:
|
||
- **基础数据模型**:`src/main/java/com/gunshi/project/hsz/model/StStbprpB.java` - 测站基础信息模型
|
||
- **行政区划**:`src/main/java/com/gunshi/project/hsz/model/StAddvcdD.java` - 行政区划数据模型
|
||
|
||
### 6.3.3 调查成果域
|
||
[调查成果域架构图]
|
||
|
||
**代码库实现**:
|
||
- **防治对象模型**:`src/main/java/com/gunshi/project/hsz/model/AttResBase.java` - 防治对象基础数据模型
|
||
- **防治部位模型**:`src/main/java/com/gunshi/project/hsz/model/AttResDetail.java` - 防治部位详细数据模型
|
||
|
||
### 6.3.4 系统管理域
|
||
[系统管理域架构图]
|
||
|
||
**代码库实现**:
|
||
- **用户管理**:基于RuoYi框架的用户权限管理
|
||
- **日志管理**:`src/main/java/com/gunshi/project/hsz/system/model/SysUserLoginLog.java` - 用户登录日志模型
|
||
- **菜单管理**:`src/main/java/com/gunshi/project/hsz/system/model/SysVisitMenuLog.java` - 菜单访问日志模型
|
||
|
||
### 6.3.5 预报域
|
||
[预报域库架构图]
|
||
|
||
**代码库实现**:
|
||
- **预报服务**:`src/main/java/com/gunshi/project/hsz/service/ForecastService.java` - 预报服务
|
||
- **GRIB2数据**:`src/main/java/com/gunshi/project/hsz/grb/RainGrib2Layer.java` - GRIB2网格数据模型
|
||
- **预报结果**:`src/main/java/com/gunshi/project/hsz/model/ForecastResults.java` - 预报结果数据模型
|
||
|
||
### 6.3.6 预警域
|
||
[预警域库架构图]
|
||
|
||
**代码库实现**:
|
||
- **预警规则模型**:`src/main/java/com/gunshi/project/hsz/model/OsmoticWarnRule.java` - 预警规则数据模型
|
||
- **预警消息模型**:`src/main/java/com/gunshi/project/hsz/model/MessageCenter.java` - 消息中心数据模型
|
||
- **预警配置**:`src/main/java/com/gunshi/project/hsz/model/AlarmSet.java` - 预警配置数据模型
|
||
- **广播预警**:`src/main/java/com/gunshi/project/hsz/model/BroadcastWarn.java` - 广播预警数据模型
|
||
|
||
### 6.3.7 预演域
|
||
[预演域库架构图]
|
||
|
||
**代码库实现**:
|
||
- **预案管理**:`src/main/java/com/gunshi/project/hsz/model/ResPlanB.java` - 预案数据模型
|
||
- **预案服务**:`src/main/java/com/gunshi/project/hsz/service/ResPlanBService.java` - 预案管理服务
|
||
|
||
### 6.3.8 预案域
|
||
[预案域库架构图]
|
||
|
||
**代码库实现**:
|
||
- **考核任务**:`src/main/java/com/gunshi/project/hsz/model/AssessTask.java` - 考核任务数据模型
|
||
- **考核对象**:`src/main/java/com/gunshi/project/hsz/model/AssessObject.java` - 考核对象数据模型
|
||
- **考核团队**:`src/main/java/com/gunshi/project/hsz/model/AssessTeam.java` - 考核团队数据模型
|
||
- **考核指标**:`src/main/java/com/gunshi/project/hsz/model/AssessIndicator.java` - 考核指标数据模型
|
||
|
||
## 6.4 数据库访问优化设计
|
||
|
||
### 6.4.1 减少数据访问
|
||
|
||
#### 6.4.1.1 数据库索引
|
||
在没有索引的世界中,对数据库的每个请求都将导致对整个表进行全面扫描。
|
||
|
||
**代码库实现**:
|
||
- **主键索引**:所有实体类主键自动创建索引
|
||
- **业务索引**:`src/main/java/com/gunshi/project/hsz/mapper/AttResBaseMapper.java:26-38` - 查询条件字段索引
|
||
- **复合索引**:根据查询模式创建复合索引
|
||
|
||
#### 6.4.1.2 只访问索引数据
|
||
为几个字段单独建立一个组合索引,可以直接只通过访问索引就能得到数据。
|
||
|
||
#### 6.4.1.3 优化SQL执行计划
|
||
执行计划是SQL在数据库中执行情况的客观反映,也是SQL性能分析和优化的参考。
|
||
|
||
**代码库实现**:
|
||
- **窗口函数**:`src/main/java/com/gunshi/project/hsz/mapper/StPptnRMapper.java:46-52` - 使用 `DISTINCT ON` 优化去重查询
|
||
- **时间函数**:`src/main/java/com/gunshi/project/hsz/mapper/AttResBaseMapper.java:66-68` - PostgreSQL 特有时间函数优化
|
||
- **分页查询**:MyBatis-Plus 分页插件实现高效分页
|
||
|
||
#### 6.4.1.4 慢查询日志分析
|
||
通过日志来实现调试应用程序中的缓慢性能。
|
||
|
||
**代码库实现**:
|
||
- **SQL日志**:`src/main/resources/config-common.yml:13` - `log-impl: org.apache.ibatis.logging.stdout.StdOutImpl`
|
||
- **性能分析**:MyBatis-Plus 性能分析插件
|
||
- **慢查询检测**:数据库慢查询日志配置
|
||
|
||
### 6.4.2 返回更少数据
|
||
|
||
#### 6.4.2.1 数据分页处理
|
||
对数据库中数据查询采用SQL分页查询,避免一次性查询数据量过大数据。
|
||
|
||
**代码库实现**:
|
||
```java
|
||
// MyBatis-Plus 分页查询实现
|
||
Page<StPptnR> page = new Page<>(pageNum, pageSize);
|
||
LambdaQueryWrapper<StPptnR> wrapper = new LambdaQueryWrapper<>();
|
||
wrapper.orderByDesc(StPptnR::getTm);
|
||
IPage<StPptnR> result = stPptnRMapper.selectPage(page, wrapper);
|
||
```
|
||
|
||
#### 6.4.2.2 只返回需要的字段
|
||
查询SQL语句去除不必要字段提高查询性能。
|
||
|
||
**代码库实现**:
|
||
- **字段选择**:通过MyBatis-Plus的`select()`方法指定查询字段
|
||
- **DTO映射**:使用VO对象进行字段映射和过滤
|
||
- **延迟加载**:对大文本字段使用延迟加载
|
||
|
||
### 6.4.3 减少交互次数
|
||
|
||
#### 6.4.3.1 BatchDML
|
||
通过使用数据库提供批量操作,减少对数据库的查询次数。
|
||
|
||
**代码库实现**:
|
||
- **批量保存**:`src/main/java/com/gunshi/project/hsz/timetask/DataTaskHsz.java:122-237` - `stPptnRService.saveBatch(rlist)`
|
||
- **批量更新**:使用MyBatis-Plus批量更新方法
|
||
- **批量删除**:级联删除优化
|
||
|
||
#### 6.4.3.2 操作符优化
|
||
使用EXISTS、NOTIN、IN等操作符优化SQL语句。
|
||
|
||
**代码库实现**:
|
||
- **Lambda查询**:`src/main/java/com/gunshi/project/hsz/service/StStbprpBService.java:44-50` - 使用 `LambdaQueryWrapper`
|
||
- **链式调用**:`StStbprpBService.java:51-56` - 流式API构建
|
||
- **条件组合**:复杂查询条件的组合优化
|
||
|
||
## 6.5 缓存机制设计
|
||
|
||
### 6.5.1 Redis缓存配置
|
||
|
||
#### 6.5.1.1 缓存配置
|
||
Redis连接、缓存策略、缓存注解的实现。
|
||
|
||
**代码库实现**:
|
||
```yaml
|
||
# config-prod.yml
|
||
spring:
|
||
data:
|
||
redis:
|
||
host: redis
|
||
port: 6379
|
||
database: 4
|
||
```
|
||
|
||
#### 6.5.1.2 缓存策略
|
||
查询缓存、缓存清除、条件缓存控制。
|
||
|
||
**代码库实现**:
|
||
- **查询缓存**:`src/main/java/com/gunshi/project/hsz/service/FileAssociationsService.java:32-38` - `@Cacheable(value=THIS_REDIS_KEY, key="#p0+':'+#p1")`
|
||
- **缓存清除**:`@CacheEvict(value=THIS_REDIS_KEY, key="#p1+':*'", allEntries=true)`
|
||
- **条件缓存**:`unless="false"` 条件性缓存控制
|
||
|
||
### 6.5.2 本地缓存实现
|
||
|
||
#### 6.5.2.1 Caffeine缓存
|
||
Spring Cache、缓存注解、缓存配置的实现。
|
||
|
||
**代码库实现**:
|
||
- **缓存启用**:`src/main/java/com/gunshi/project/hsz/Main.java:28` - `@EnableCaching` 启用缓存支持
|
||
- **缓存注解**:方法级别缓存控制
|
||
- **缓存配置**:`config-common.yml` - 缓存相关配置
|
||
|
||
## 6.6 数据库安全实现
|
||
|
||
### 6.6.1 访问控制
|
||
|
||
#### 6.6.1.1 用户认证
|
||
数据库用户、密码加密、权限分离的实现。
|
||
|
||
**代码库实现**:
|
||
- **数据库用户**:`config-prod.yml:10` - 专用数据库用户配置
|
||
- **密码加密**:数据库连接密码加密存储
|
||
- **权限分离**:读写权限分离
|
||
|
||
#### 6.6.1.2 SQL注入防护
|
||
参数化查询、输入验证、XSS防护的实现。
|
||
|
||
**代码库实现**:
|
||
- **参数化查询**:MyBatis参数化查询自动防护
|
||
- **输入验证**:`@Size`、`@NotBlank`等验证注解
|
||
- **XSS防护**:`src/main/java/com/gunshi/core/xss/jackson/JacksonDeserializerXssStringDefender.java` - Jackson反序列化XSS防护
|
||
|
||
### 6.6.2 数据加密
|
||
|
||
#### 6.6.2.1 敏感数据保护
|
||
连接加密、数据脱敏、审计日志的实现。
|
||
|
||
**代码库实现**:
|
||
- **连接加密**:PostgreSQL SSL连接加密
|
||
- **数据脱敏**:敏感信息查询时脱敏处理
|
||
- **审计日志**:数据库操作审计日志
|
||
|
||
## 6.7 数据库监控与维护
|
||
|
||
### 6.7.1 性能监控
|
||
|
||
#### 6.7.1.1 SQL日志
|
||
SQL输出、性能分析、慢查询检测的实现。
|
||
|
||
**代码库实现**:
|
||
- **SQL输出**:`config-common.yml` - `log-impl: org.apache.ibatis.logging.stdout.StdOutImpl`
|
||
- **性能分析**:MyBatis-Plus性能分析插件
|
||
- **慢查询检测**:数据库慢查询日志配置
|
||
|
||
#### 6.7.1.2 连接池监控
|
||
连接状态、连接泄漏、性能指标的实现。
|
||
|
||
**代码库实现**:
|
||
- **连接状态**:HikariCP连接池状态监控
|
||
- **连接泄漏**:连接泄漏检测和处理
|
||
- **性能指标**:连接使用率、等待时间等指标
|
||
|
||
### 6.7.2 数据备份与恢复
|
||
|
||
#### 6.7.2.1 备份策略
|
||
主备切换、数据同步、定期备份的实现。
|
||
|
||
**代码库实现**:
|
||
- **主备切换**:`config-prod.yml:12-16` - 自动主备切换
|
||
- **数据同步**:主从数据库实时同步
|
||
- **定期备份**:定时任务自动备份
|
||
|
||
#### 6.7.2.2 恢复机制
|
||
故障转移、数据恢复、一致性检查的实现。
|
||
|
||
**代码库实现**:
|
||
- **故障转移**:自动故障转移机制
|
||
- **数据恢复**:数据恢复流程和工具
|
||
- **一致性检查**:数据一致性验证
|
||
|
||
## 6.8 关键数据模型设计
|
||
|
||
### 6.8.1 监测数据模型
|
||
|
||
#### 6.8.1.1 降雨监测数据
|
||
```java
|
||
@TableName("public.st_pptn_r")
|
||
public class StPptnR {
|
||
@TableId(value = "id", type = IdType.AUTO)
|
||
private Long id;
|
||
|
||
@TableField(value = "stcd")
|
||
@Size(max = 20, message = "测站编码最大长度要小于20")
|
||
private String stcd; // 测站编码
|
||
|
||
@TableField(value = "drp")
|
||
private BigDecimal drp; // 降雨量
|
||
|
||
@TableField(value = "tm")
|
||
@NotNull(message = "时间不能为空")
|
||
private Date tm; // 时间
|
||
|
||
// 其他字段...
|
||
}
|
||
```
|
||
|
||
#### 6.8.1.2 水位监测数据
|
||
```java
|
||
@TableName("public.st_rsvr_r")
|
||
public class StRsvrR {
|
||
@TableId(value = "id", type = IdType.AUTO)
|
||
private Long id;
|
||
|
||
@TableField(value = "stcd")
|
||
private String stcd; // 测站编码
|
||
|
||
@TableField(value = "rz")
|
||
private BigDecimal rz; // 水位
|
||
|
||
@TableField(value = "tm")
|
||
private Date tm; // 时间
|
||
|
||
// 其他字段...
|
||
}
|
||
```
|
||
|
||
### 6.8.2 预警数据模型
|
||
|
||
#### 6.8.2.1 预警规则数据
|
||
```java
|
||
@TableName("public.osmotic_warn_rule")
|
||
public class OsmoticWarnRule {
|
||
@TableId(value = "id", type = IdType.AUTO)
|
||
private Long id;
|
||
|
||
@TableField(value = "rule_name")
|
||
private String ruleName; // 规则名称
|
||
|
||
@TableField(value = "rule_type")
|
||
private Integer ruleType; // 规则类型
|
||
|
||
@TableField(value = "threshold_value")
|
||
private BigDecimal thresholdValue; // 阈值
|
||
|
||
@TableField(value = "logic_relation")
|
||
private String logicRelation; // 逻辑关系
|
||
|
||
@TableField(value = "status")
|
||
private Integer status; // 状态
|
||
|
||
// 其他字段...
|
||
}
|
||
```
|
||
|
||
#### 6.8.2.2 消息中心数据
|
||
```java
|
||
@TableName("public.message_center")
|
||
public class MessageCenter {
|
||
@TableId(value = "id", type = IdType.AUTO)
|
||
private Long id;
|
||
|
||
@TableField(value = "message_type")
|
||
private Integer messageType; // 消息类型
|
||
|
||
@TableField(value = "message_content")
|
||
private String messageContent; // 消息内容
|
||
|
||
@TableField(value = "send_status")
|
||
private Integer sendStatus; // 发送状态
|
||
|
||
@TableField(value = "send_time")
|
||
private Date sendTime; // 发送时间
|
||
|
||
// 其他字段...
|
||
}
|
||
```
|
||
|
||
### 6.8.3 业务数据模型
|
||
|
||
#### 6.8.3.1 防治对象数据
|
||
```java
|
||
@TableName("public.att_res_base")
|
||
public class AttResBase {
|
||
@TableId(value = "res_code", type = IdType.AUTO)
|
||
private Long resCode; // 防治对象编码
|
||
|
||
@TableField(value = "res_name")
|
||
private String resName; // 防治对象名称
|
||
|
||
@TableField(value = "res_type")
|
||
private Integer resType; // 防治对象类型
|
||
|
||
@TableField(value = "adcd")
|
||
private String adcd; // 行政区划编码
|
||
|
||
@TableField(value = "status")
|
||
private Integer status; // 状态
|
||
|
||
// 其他字段...
|
||
}
|
||
```
|
||
|
||
#### 6.8.3.2 考核任务数据
|
||
```java
|
||
@TableName("public.assess_task")
|
||
public class AssessTask {
|
||
@TableId(value = "id", type = IdType.AUTO)
|
||
private Long id;
|
||
|
||
@TableField(value = "task_name")
|
||
private String taskName; // 任务名称
|
||
|
||
@TableField(value = "task_type")
|
||
private Integer taskType; // 任务类型
|
||
|
||
@TableField(value = "task_status")
|
||
private Integer taskStatus; // 任务状态
|
||
|
||
@TableField(value = "create_time")
|
||
private Date createTime; // 创建时间
|
||
|
||
// 其他字段...
|
||
}
|
||
```
|
||
|
||
## 6.9 数据库扩展性设计
|
||
|
||
### 6.9.1 分库分表准备
|
||
|
||
#### 6.9.1.1 分片策略
|
||
水平分片、垂直分片、读写分离的实现。
|
||
|
||
**代码库实现**:
|
||
- **水平分片**:按时间或业务进行数据分片
|
||
- **垂直分片**:按业务模块进行数据库拆分
|
||
- **读写分离**:读写分离架构支持
|
||
|
||
#### 6.9.1.2 扩展架构
|
||
微服务支持、云原生支持、多租户支持的实现。
|
||
|
||
**代码库实现**:
|
||
- **微服务支持**:数据库架构支持微服务拆分
|
||
- **云原生支持**:容器化数据库部署支持
|
||
- **多租户支持**:多租户数据隔离机制 |