# 第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 page = new Page<>(pageNum, pageSize); LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.orderByDesc(StPptnR::getTm); IPage 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 扩展架构 微服务支持、云原生支持、多租户支持的实现。 **代码库实现**: - **微服务支持**:数据库架构支持微服务拆分 - **云原生支持**:容器化数据库部署支持 - **多租户支持**:多租户数据隔离机制