17 KiB
第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做主备切换。解决单点问题,保障数据库高可用性。
代码库实现:
# 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分页查询,避免一次性查询数据量过大数据。
代码库实现:
// 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连接、缓存策略、缓存注解的实现。
代码库实现:
# 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 降雨监测数据
@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 水位监测数据
@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 预警规则数据
@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 消息中心数据
@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 防治对象数据
@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 考核任务数据
@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 扩展架构
微服务支持、云原生支持、多租户支持的实现。
代码库实现:
- 微服务支持:数据库架构支持微服务拆分
- 云原生支持:容器化数据库部署支持
- 多租户支持:多租户数据隔离机制