慧知开源充电桩多协议微服务平台慧知开源充电桩多协议微服务平台
首页
介绍
快速了解
多协议模块
GitHub
首页
介绍
快速了解
多协议模块
GitHub
  • 文档

    • 介绍
    • 快速了解
    • 环境部署
    • 项目介绍
    • 后台手册
    • 前端手册
    • 组件文档
    • 更新日志
  • 微服务

    • 服务网关
    • 认证中心
    • 注册中心
    • 配置中心
    • 服务调用
    • 服务监控
    • 系统接口
    • 链路追踪
    • 熔断和降级
    • 分布式文件
    • 分布式事务
    • 分布式日志
    • 应用容器部署
  • 多协议模块

    • 系统概述
    • 技术栈与依赖
    • 开发者指南
    • 部署与配置
    • 消息队列集成
    • 缓存架构
    • 监控与运维
    • 安全机制
    • 数据模型与数据库设计
    • 架构设计
      • 架构设计
      • 微服务架构
      • 数据流分析
      • 架构模式
    • API接口参考
      • API接口参考
      • gRPC API
      • REST API
    • 核心模块详解
      • 核心模块详解
      • 协议处理框架
      • 设备管理模块
      • 协议实现模块
        • 云快充协议实现
        • 核心架构与初始化
        • 上行消息处理
        • 下行消息处理
        • 绿能协议实现
        • 核心架构
        • 下行消息处理
  • 其他

    • 常见问题
    • 捐赠支持

数据模型与数据库设计

目录

  1. 核心实体数据模型
  2. 实体关系与ER图
  3. 属性实体设计
  4. 数据库表结构与索引
  5. 数据访问层设计
  6. 数据生命周期管理

核心实体数据模型

充电站 (Station)

充电站实体表示物理充电站点,包含站点的基本信息和地理位置。

属性说明:

  • id: UUID类型,主键,全局唯一标识符
  • createdTime: 时间戳,记录创建时间
  • updatedTime: 时间戳,记录最后更新时间
  • additionalInfo: JSON类型,存储额外的扩展信息
  • stationName: 字符串类型,站点名称,非空
  • stationCode: 字符串类型,站点编码,全局唯一,非空
  • longitude: 浮点类型,经度坐标
  • latitude: 浮点类型,纬度坐标
  • province: 字符串类型,省份信息
  • city: 字符串类型,城市信息
  • county: 字符串类型,区县信息
  • address: 字符串类型,详细地址
  • version: 整数类型,版本号,用于乐观锁控制

Section sources

  • [Station.java](file://mp-app/src/main/java/com/witos/mp/app/dal/entity/Station.java#L1-L65)

充电桩 (Pile)

充电桩实体表示充电站内的具体充电设备,与充电站存在一对多关系。

属性说明:

  • id: UUID类型,主键,全局唯一标识符
  • createdTime: 时间戳,记录创建时间
  • updatedTime: 时间戳,记录最后更新时间
  • additionalInfo: JSON类型,存储额外的扩展信息
  • pileName: 字符串类型,充电桩名称,非空
  • pileCode: 字符串类型,充电桩编码,全局唯一,非空
  • protocol: 字符串类型,通信协议类型,非空
  • stationId: UUID类型,外键,关联到充电站实体
  • brand: 字符串类型,品牌信息
  • model: 字符串类型,型号信息
  • manufacturer: 字符串类型,制造商信息
  • type: 枚举类型,充电桩类型(交流AC/直流DC),非空
  • version: 整数类型,版本号,用于乐观锁控制

Section sources

  • [Pile.java](file://mp-app/src/main/java/com/witos/mp/app/dal/entity/Pile.java#L1-L64)
  • [PileTypeEnum.java](file://mp-app/src/main/java/com/witos/mp/app/dal/config/ibatis/enums/PileTypeEnum.java#L1-L22)

充电枪 (Gun)

充电枪实体表示充电桩上的具体充电接口,与充电桩存在一对多关系。

属性说明:

  • id: UUID类型,主键,全局唯一标识符
  • createdTime: 时间戳,记录创建时间
  • updatedTime: 时间戳,记录最后更新时间
  • additionalInfo: 字符串类型,存储额外的扩展信息
  • gunNo: 字符串类型,枪编号,在同一充电桩下唯一,非空
  • gunName: 字符串类型,充电枪名称,非空
  • gunCode: 字符串类型,充电枪编码,全局唯一,非空
  • stationId: UUID类型,外键,关联到充电站实体
  • pileId: UUID类型,外键,关联到充电桩实体
  • version: 整数类型,版本号,用于乐观锁控制

Section sources

  • [Gun.java](file://mp-app/src/main/java/com/witos/mp/app/dal/entity/Gun.java#L1-L56)

实体关系与ER图

充电站、充电桩和充电枪之间存在明确的层次结构关系:一个充电站包含多个充电桩,一个充电桩包含多个充电枪。

erDiagram
STATION {
uuid id PK
timestamp created_time
timestamp updated_time
jsonb additional_info
varchar station_name
varchar station_code UK
double precision longitude
double precision latitude
varchar province
varchar city
varchar county
varchar address
int version
}
PILE {
uuid id PK
timestamp created_time
timestamp updated_time
jsonb additional_info
varchar pile_name
varchar pile_code UK
varchar protocol
uuid station_id FK
varchar brand
varchar model
varchar manufacturer
varchar type
int version
}
GUN {
uuid id PK
timestamp created_time
timestamp updated_time
varchar additional_info
varchar gun_no
varchar gun_name
varchar gun_code UK
uuid station_id FK
uuid pile_id FK
int version
}
STATION ||--o{ PILE : "包含"
PILE ||--o{ GUN : "包含"

Diagram sources

  • [Station.java](file://mp-app/src/main/java/com/witos/mp/app/dal/entity/Station.java#L1-L65)
  • [Pile.java](file://mp-app/src/main/java/com/witos/mp/app/dal/entity/Pile.java#L1-L64)
  • [Gun.java](file://mp-app/src/main/java/com/witos/mp/app/dal/entity/Gun.java#L1-L56)
  • [schema-init.sql](file://mp-app/src/main/resources/sql/schema-init.sql#L45-L130)

属性实体设计

Attribute实体架构

Attribute实体采用灵活的键值对(K-V)存储模式,用于存储设备的动态属性,如电压、电流、状态等实时数据。

表结构设计特点:

  • 复合主键: 由entity_id和attr_key组成,确保每个实体的每个属性键唯一
  • 多值类型字段: 为支持不同数据类型,表中包含多种类型的值字段
  • 时间戳: last_update_ts记录属性最后更新时间
  • 版本控制: version字段用于乐观锁控制

多值类型字段:

  • bool_v: 布尔值,存储true/false类型数据
  • str_v: 字符串值,存储文本数据,最大长度10,000,000字符
  • long_v: 长整型值,存储大整数
  • dbl_v: 双精度值,存储浮点数
  • json_v: JSON值,存储复杂结构化数据

Section sources

  • [Attribute.java](file://mp-app/src/main/java/com/witos/mp/app/dal/entity/Attribute.java#L1-L102)

属性与核心实体的关联

Attribute实体通过entity_id字段与Station、Pile和Gun实体关联,实现一对多的关系。

erDiagram
STATION ||--o{ ATTRIBUTE : "拥有"
PILE ||--o{ ATTRIBUTE : "拥有"
GUN ||--o{ ATTRIBUTE : "拥有"
ATTRIBUTE {
uuid entity_id PK,FK
varchar attr_key PK
boolean bool_v
varchar str_v
bigint long_v
double precision dbl_v
json json_v
bigint last_update_ts
int version
}

属性键枚举 (AttrKeyEnum) 系统定义了标准的属性键枚举,确保属性命名的一致性:

  • STATUS: 状态
  • CONNECTED_AT: 连接时间
  • DISCONNECTED_AT: 断开连接时间
  • LAST_ACTIVE_TIME: 最后活跃时间
  • GUN_RUN_STATUS: 充电枪运行状态
  • LOCK_STATUS: 地锁状态
  • PARK_STATUS: 车位状态

Diagram sources

  • [Attribute.java](file://mp-app/src/main/java/com/witos/mp/app/dal/entity/Attribute.java#L1-L102)
  • [AttrKeyEnum.java](file://mp-app/src/main/java/com/witos/mp/app/data/kv/AttrKeyEnum.java#L1-L69)

数据库表结构与索引

表结构详情

根据schema-init.sql文件,数据库包含以下主要表:

t_station (充电站表)

  • 主键: id
  • 唯一索引: uni_station_code on station_code
  • 字段: id, created_time, updated_time, additional_info, station_name, station_code, longitude, latitude, province, city, county, address, version

t_pile (充电桩表)

  • 主键: id
  • 外键: station_id references t_station(id)
  • 唯一索引: uni_pile_code on pile_code
  • 字段: id, created_time, updated_time, additional_info, pile_name, pile_code, protocol, station_id, brand, model, manufacturer, type, version

t_gun (充电枪表)

  • 主键: id
  • 外键: station_id references t_station(id), pile_id references t_pile(id)
  • 唯一索引: uni_gun_pile_gun_no on (pile_id, gun_no), uni_gun_code on gun_code
  • 字段: id, created_time, updated_time, additional_info, gun_no, gun_name, gun_code, station_id, pile_id, version

t_attr (属性表)

  • 复合主键: (entity_id, attr_key)
  • 字段: entity_id, attr_key, bool_v, str_v, long_v, dbl_v, json_v, last_update_ts, version

索引设计与查询优化

数据库设计了多个索引以优化查询性能:

唯一性约束索引:

  • uni_station_code: 确保充电站编码全局唯一
  • uni_pile_code: 确保充电桩编码全局唯一
  • uni_gun_code: 确保充电枪编码全局唯一
  • uni_gun_pile_gun_no: 确保同一充电桩下枪编号唯一

查询性能优化: 这些索引不仅保证了数据的完整性,还显著提升了基于编码的查询性能。例如,通过充电桩编码查询充电桩信息时,可以直接利用 uni_pile_code索引进行快速查找。

Section sources

  • [schema-init.sql](file://mp-app/src/main/resources/sql/schema-init.sql#L1-L130)

数据访问层设计

MyBatis Mapper接口设计

数据访问层采用MyBatis框架,通过Mapper接口与XML映射文件配合工作。

核心Mapper接口:

  • StationMapper: 继承自BaseMapper<Station>,提供基础的CRUD操作
  • PileMapper: 扩展了基础操作,包含自定义查询方法
  • GunMapper: 扩展了基础操作,包含自定义查询方法
  • AttributeMapper: 提供属性数据的特定访问方法

Mapper接口与XML映射配合

Mapper接口定义了数据访问方法,而具体的SQL语句在对应的XML文件中实现,这种分离设计提高了代码的可维护性。

PileMapper示例:

IPage<PileWithStatusResponse> selectPileWithStatusPage(
    Page<PileWithStatusResponse> page, 
    @Param("request") PileQueryRequest request,
    @Param("statusKey") AttrKeyEnum statusKey,
    @Param("connectedAtKey") AttrKeyEnum connectedAtKey,
    @Param("disconnectedAtKey") AttrKeyEnum disconnectedAtKey,
    @Param("lastActiveTimeKey") AttrKeyEnum lastActiveTimeKey
);

对应的SQL在PileMapper.xml中定义,但项目中使用了注解方式直接在接口中定义SQL,体现了MyBatis-Plus的特性。

AttributeMapper XML映射:

<mapper namespace="com/witos.mp.app.dal.mapper.AttributeMapper">
    <select id="findByEntity" resultType="com/witos.mp.app.dal.entity.Attribute">
        SELECT * FROM t_attr WHERE entity_id = #{entityId}
    </select>
    
    <select id="findByEntityAndKey" resultType="com/witos.mp.app.dal.entity.Attribute">
        SELECT * FROM t_attr WHERE entity_id = #{entityId} AND attr_key = #{attrKey}
    </select>
    
    <delete id="deleteByEntityIdAndKey">
        DELETE FROM t_attr WHERE entity_id = #{entityId} AND attr_key = #{attrKey}
    </delete>
</mapper>

这种设计模式的优势:

  1. 关注点分离: Java接口定义方法签名,XML文件定义SQL实现
  2. 可维护性: SQL语句集中管理,便于修改和优化
  3. 类型安全: MyBatis通过接口提供类型安全的数据访问
  4. 灵活性: 复杂SQL可以在XML中使用动态SQL标签构建

Section sources

  • [StationMapper.java](file://mp-app/src/main/java/com/witos/mp/app/dal/mapper/StationMapper.java#L1-L15)
  • [PileMapper.java](file://mp-app/src/main/java/com/witos/mp/app/dal/mapper/PileMapper.java#L1-L77)
  • [GunMapper.java](file://mp-app/src/main/java/com/witos/mp/app/dal/mapper/GunMapper.java#L1-L131)
  • [AttributeMapper.java](file://mp-app/src/main/java/com/witos/mp/app/dal/mapper/AttributeMapper.java#L1-L53)
  • [AttributeMapper.xml](file://mp-app/src/main/resources/mapper/AttributeMapper.xml#L1-L43)

数据生命周期管理

状态清洗与初始化

系统在启动时执行状态清洗操作,确保充电桩状态的一致性。

StatusCleanupInitializingBean组件:

  • 在Spring容器初始化时执行
  • 执行充电桩状态的全量清洗
  • 如果失败会阻止应用启动,确保数据状态一致性
  • 分页处理充电桩,每次处理1000个,避免内存溢出

状态决策逻辑: 根据会话状态、数据库状态和超时时间决定目标状态:

  • 检查充电桩是否有活跃的会话连接
  • 结合当前数据库状态和配置的超时阈值
  • 决定最终的目标状态(在线/离线)

Section sources

  • [StatusCleanupInitializingBean.java](file://mp-app/src/main/java/com/witos/mp/app/initializing/StatusCleanupInitializingBean.java#L1-L169)

批量数据处理与队列机制

系统实现了高效的批量数据处理机制,用于优化数据库写入性能。

SqlBlockingQueueWrapper设计:

  • 使用阻塞队列实现数据批量处理
  • 支持多线程并行处理
  • 可配置批处理大小和最大延迟时间
  • 提供统计信息打印功能

批处理参数:

  • logName: 日志名称
  • batchSize: 批处理大小
  • maxDelay: 最大延迟时间(毫秒)
  • statsPrintIntervalMs: 统计信息打印间隔
  • statsNamePrefix: 统计名称前缀
  • batchSortEnabled: 是否启用批处理排序
  • withResponse: 是否需要响应

数据处理流程:

  1. 数据元素被添加到阻塞队列
  2. 单线程消费者定期从队列中获取数据
  3. 当达到批处理大小或超时后,执行批量保存
  4. 支持对批处理数据进行排序,避免集群模式下的死锁

Section sources

  • [SqlBlockingQueueWrapper.java](file://mp-app/src/main/java/com/witos/mp/app/dal/repository/batch/SqlBlockingQueueWrapper.java#L1-L58)
  • [SqlBlockingQueue.java](file://mp-app/src/main/java/com/witos/mp/app/dal/repository/batch/SqlBlockingQueue.java#L1-L58)
  • [SqlBlockingQueueParams.java](file://mp-app/src/main/java/com/witos/mp/app/dal/repository/batch/SqlBlockingQueueParams.java#L1-L24)
  • [ScheduledLogExecutorComponent.java](file://mp-app/src/main/java/com/witos/mp/app/dal/repository/batch/ScheduledLogExecutorComponent.java#L1-L40)
最近更新:: 2026/5/1 15:39
Contributors: feng
Prev
安全机制
Next
架构设计