370 lines
18 KiB
Plaintext
370 lines
18 KiB
Plaintext
================================================================================
|
||
jeecg-module-sync 模块 — AI辅助代码编辑上下文文件
|
||
================================================================================
|
||
|
||
一、模块概述
|
||
--------------------------------------------------------------------------------
|
||
jeecg-module-sync 是源项分析系统(STAS)中的数据同步模块,负责在Oracle和PostgreSQL
|
||
数据库之间进行数据同步。支持定时任务调度、增量同步(按日期/ID范围)、同步策略管理、
|
||
同步日志记录和同步统计等功能。
|
||
|
||
父工程: jeecg-boot-parent 3.8.1
|
||
Java版本: 17
|
||
核心依赖: jeecg-boot-base-core(提供实体、Mapper、工具类等基础能力)
|
||
框架: Spring Boot + MyBatis-Plus + Quartz + Swagger/OpenAPI
|
||
|
||
|
||
二、目录结构与文件清单
|
||
--------------------------------------------------------------------------------
|
||
jeecg-module-sync/
|
||
├── pom.xml
|
||
└── src/main/java/org/jeecg/
|
||
├── OracleSync.java # 独立工具类:Oracle-to-Oracle同步(main方法入口)
|
||
├── OracleToPgSync.java # 独立工具类:Oracle-to-PostgreSQL建表同步(main方法入口)
|
||
├── dataSource/ # 数据源管理子模块
|
||
│ ├── controller/StasDataSourceController.java
|
||
│ ├── service/IStasDataSourceService.java
|
||
│ ├── service/impl/StasDataSourceServiceImpl.java
|
||
│ └── vo/TableColumnVO.java
|
||
├── stasSyncStrategy/ # 同步策略管理子模块
|
||
│ ├── controller/StasSyncStrategyController.java
|
||
│ ├── service/IStasSyncStrategyService.java
|
||
│ └── service/impl/StasSyncStrategyServiceImpl.java
|
||
├── syncLog/ # 同步日志子模块
|
||
│ ├── controller/StasSyncLogController.java
|
||
│ ├── service/IStasSyncLogService.java
|
||
│ └── service/impl/StasSyncLogServiceImpl.java
|
||
├── syncNum/ # 同步数量统计子模块
|
||
│ ├── controller/StasSyncNumController.java
|
||
│ ├── service/IStasSyncNumService.java
|
||
│ ├── service/impl/StasSyncNumServiceImpl.java
|
||
│ └── vo/PieChartVO.java
|
||
├── syncRecord/ # 同步记录子模块
|
||
│ ├── controller/StasSyncRecordController.java
|
||
│ ├── service/IStasSyncRecordService.java
|
||
│ ├── service/impl/StasSyncRecordServiceImpl.java
|
||
│ └── vo/SyncRecordVO.java, TaskHisStatsVO.java, TaskStatsResultVO.java
|
||
├── taskConfig/ # 任务配置子模块(核心)
|
||
│ ├── controller/StasTaskConfigController.java
|
||
│ ├── job/SyncDataJob.java # Quartz Job执行类
|
||
│ ├── service/IStasTaskConfigService.java
|
||
│ └── service/impl/StasTaskConfigServiceImpl.java
|
||
├── quartz/ # Quartz定时任务管理
|
||
│ ├── service/IQuartzJobService.java
|
||
│ └── service/impl/QuartzJobServiceImpl.java
|
||
└── vo/ # 模块内VO
|
||
├── DateRangeVO.java
|
||
├── IdRangeVO.java
|
||
├── MindMapVO.java
|
||
├── TableInfoVO.java
|
||
└── UserInfoVO.java
|
||
|
||
|
||
三、数据库实体(定义在 jeecg-boot-base-core 中)
|
||
--------------------------------------------------------------------------------
|
||
本模块的实体类统一定义在 jeecg-boot-base-core 的 org.jeecg.modules.base.entity 包中,
|
||
由 jeecg-boot-base-core 的 org.jeecg.modules.base.mapper 提供 MyBatis-Plus Mapper 接口。
|
||
|
||
1. StasDataSource(表 stas_data_source)— 数据源配置
|
||
字段: id(ASSIGN_ID), createBy, createTime, updateBy, updateTime,
|
||
instanceName(实例名), type(数据库类型: 0=Oracle,1=PostgreSQL),
|
||
port, serveId(服务名), dbLink, username, password, remark,
|
||
delFlag(逻辑删除), ipAddress, description
|
||
|
||
2. StasSyncStrategy(表 stas_sync_strategy)— 同步策略
|
||
字段: id(ASSIGN_ID), createBy, createTime, updateBy, updateTime,
|
||
taskId(关联任务ID), sourceOwner(源用户/Schema), targetOwner(目标用户/Schema),
|
||
tableName(同步表名), columnName(依据字段名), syncOrigin(同步位置/断点)
|
||
|
||
3. StasTaskConfig(表 stas_task_config)— 任务配置
|
||
字段: id(ASSIGN_ID), createBy, createTime, updateBy, updateTime,
|
||
taskName(任务名称), quartzId(关联Quartz任务ID), cron(Cron表达式),
|
||
sourceId(源库ID), targetId(目标库ID), syncCount(批次数量), syncDay(批次天数),
|
||
taskStatus(0=未开始,1=进行中), description,
|
||
sourceName(@TableField(exist=false)), targetName(@TableField(exist=false))
|
||
|
||
4. StasSyncLog(表 stas_sync_log)— 同步日志
|
||
字段: id(ASSIGN_ID), recordId(关联记录ID), startTime, description
|
||
|
||
5. StasSyncNum(表 stas_sync_num)— 同步数量
|
||
字段: id(ASSIGN_ID), recordId(关联记录ID), tableName, syncNum(同步条数)
|
||
|
||
6. StasSyncRecord(表 stas_sync_record)— 同步记录
|
||
字段: id(ASSIGN_ID), taskId, sourceId, targetId, startTime, endTime
|
||
|
||
7. QuartzJob(表 sys_quartz_job)— Quartz定时任务
|
||
字段: id(ASSIGN_ID), createBy, createTime, delFlag, updateBy, updateTime,
|
||
jobClassName, cronExpression, parameter, description, status(0=正常,-1=停止)
|
||
|
||
|
||
四、核心枚举与常量(定义在 jeecg-boot-base-core 中)
|
||
--------------------------------------------------------------------------------
|
||
1. SourceDataTypeEnum:
|
||
ORACLE(0, "ORACLE"), POSTGRES(1, "POSTGRES")
|
||
|
||
2. SyncTaskStatusEnum:
|
||
NOT_STARTED(0), IN_OPERATION(1)
|
||
|
||
3. QuartzJobConstant:
|
||
JOB_CLASS_NAME = "org.jeecg.taskConfig.job.SyncDataJob"
|
||
|
||
4. DBUtil 工具类:
|
||
- ORACLE_DRIVER = "oracle.jdbc.OracleDriver"
|
||
- POSTGRES_DRIVER = "org.postgresql.Driver"
|
||
- ORACLE_URL_PREFIX = "jdbc:oracle:thin:@"
|
||
- POSTGRES_URL_PREFIX = "jdbc:postgresql://"
|
||
- getUrl(ip, port, serveId) → 构建Oracle JDBC URL
|
||
- getPgUrl(ip, port, serveId) → 构建PostgreSQL JDBC URL
|
||
- getConnection(url, username, password, driver, type) → 获取JDBC连接
|
||
type=0: PostgreSQL(无超时设置), type=1: Oracle(设置CONNECT_TIMEOUT=300s, ReadTimeout=1200s)
|
||
- close(conn, stmt, rs) → 释放资源
|
||
|
||
|
||
五、Mapper XML(定义在 jeecg-boot-base-core 中)
|
||
--------------------------------------------------------------------------------
|
||
StasSyncRecordMapper.xml — 同步记录统计查询:
|
||
- taskHistoryStats: 关联 stas_task_config + stas_sync_record + stas_sync_num,查历史同步详情
|
||
- taskStatsDay: 按日统计同步数量(TO_CHAR(start_time,'YYYY-MM-DD'))
|
||
- taskStatsMonth: 按月统计同步数量(TO_CHAR(start_time,'YYYY-MM-DD'))
|
||
|
||
|
||
六、API接口清单
|
||
--------------------------------------------------------------------------------
|
||
1. 数据源管理 — StasDataSourceController (/dataSource)
|
||
GET /list — 分页查询数据源(支持instanceName模糊查询)
|
||
GET /userList — 查询数据源下所有用户(Oracle: ALL_USERS; PG: information_schema.schemata)
|
||
GET /targetUser — 查询目标数据源用户(通过taskId关联查targetId)
|
||
GET /tableList — 查询数据源下指定用户的所有表
|
||
GET /fieldList — 查询数据源表字段
|
||
GET /testConnection — 数据库连接测试
|
||
GET /checkInstanceName — 数据库名称唯一性校验
|
||
POST /add — 添加数据源
|
||
PUT /edit — 编辑数据源
|
||
DELETE /delete — 删除数据源(单个)
|
||
DELETE /deleteBatch — 批量删除数据源
|
||
GET /queryById — 通过ID查询
|
||
GET /queryall — 查询所有数据源
|
||
|
||
2. 同步策略 — StasSyncStrategyController (/syncStrategy)
|
||
GET /list — 分页查询同步策略
|
||
POST /createTargetTables — 在目标库创建表结构并保存策略
|
||
POST /add — 添加同步策略
|
||
PUT/POST /edit — 编辑同步策略
|
||
DELETE /delete — 删除同步策略
|
||
DELETE /deleteBatch — 批量删除同步策略
|
||
GET /queryById — 通过ID查询
|
||
GET /exportXls — 导出Excel
|
||
POST /importExcel — 导入Excel
|
||
|
||
3. 同步日志 — StasSyncLogController (/stasSyncLog)
|
||
GET /list — 分页查询同步日志(按start_time升序)
|
||
|
||
4. 同步数量 — StasSyncNumController (/stasSyncNum)
|
||
GET /list — 按表名分组统计同步数量(返回PieChartVO饼图数据)
|
||
|
||
5. 同步记录 — StasSyncRecordController (/stasSyncRecord)
|
||
GET /list — 分页查询同步记录(关联数据源名称,支持时间区间过滤)
|
||
GET /taskHisSta — 历史同步数量统计
|
||
GET /taskStatsDay — 按日统计最近一个月同步数量
|
||
GET /taskStatsMonth — 按月统计最近一年同步数量
|
||
|
||
6. 任务配置 — StasTaskConfigController (/taskConfig)
|
||
GET /list — 分页查询任务(关联数据源名称)
|
||
GET /getMindMap — 数据表思维导图(异步并行查询)
|
||
POST /add — 添加任务(含创建Quartz Job)
|
||
PUT/POST /edit — 编辑任务(含更新Quartz Job)
|
||
DELETE /delete — 删除任务(含删除Quartz Job和关联策略)
|
||
GET /pause — 暂停定时任务
|
||
GET /resume — 启动定时任务
|
||
GET /execute — 立即执行定时任务
|
||
GET /syncDataByFieldType — 手动触发同步
|
||
DELETE /deleteBatch — 批量删除任务
|
||
GET /queryById — 通过ID查询
|
||
GET /exportXls — 导出Excel
|
||
POST /importExcel — 导入Excel
|
||
|
||
|
||
七、核心业务逻辑详解
|
||
--------------------------------------------------------------------------------
|
||
7.1 数据同步流程(SyncDataJob / StasTaskConfigServiceImpl.syncDataByFieldType)
|
||
|
||
执行链路:
|
||
StasTaskConfigController.execute/手动触发
|
||
→ StasTaskConfigServiceImpl.syncDataByFieldType(taskId) [Service层版本,仅支持Oracle]
|
||
→ 或通过 QuartzJobService.execute → SyncDataJob.execute → SyncDataJob.syncDataByFieldType [Job版本,支持Oracle+PG]
|
||
|
||
核心步骤:
|
||
1. 根据taskId获取 StasTaskConfig → 获取源/目标 StasDataSource
|
||
2. 创建 StasSyncRecord 记录(记录同步开始时间)
|
||
3. 构建源/目标JDBC连接
|
||
4. 获取该任务下所有 StasSyncStrategy
|
||
5. 对每个策略:
|
||
a. 判断依据字段类型(isDateColumn)
|
||
b. 如果是日期类型 → syncByDateRange(按syncDay天数为批次)
|
||
c. 如果是ID类型 → syncByIdRange(按syncCount条数为批次)
|
||
6. 更新 StasSyncRecord 结束时间
|
||
|
||
7.2 按日期范围同步(syncByDateRange)
|
||
- 获取源表日期范围(MIN/MAX)
|
||
- 读取 syncOrigin 作为上次断点
|
||
- 从断点开始,每次同步 syncDay 天
|
||
- 若结束日期超过最大日期,先删除目标库中最后一天的数据(避免重复)
|
||
- Oracle条件: BETWEEN TO_DATE('...', 'YYYY-MM-DD HH24:MI:SS')
|
||
- PostgreSQL条件: BETWEEN TIMESTAMP '...'
|
||
- 同步完成后更新 syncOrigin 为当前结束日期
|
||
|
||
7.3 按ID范围同步(syncByIdRange)
|
||
- 获取源表ID范围(MIN/MAX)
|
||
- 读取 syncOrigin 作为上次断点(从断点+1开始)
|
||
- 每次同步 syncCount 条
|
||
- 若结束ID超过最大ID,先删除目标库中最后一条的数据
|
||
- 同步完成后更新 syncOrigin 为当前结束ID
|
||
|
||
7.4 批量数据同步(syncDataBatch)
|
||
- 源库 SELECT * FROM "OWNER"."TABLE" WHERE ...
|
||
- fetchSize: 5000(优化大表读取)
|
||
- 目标库 INSERT INTO ... VALUES (?, ?, ...)
|
||
- batchSize: 5000 提交一次
|
||
- 特殊处理: Oracle→PG时,TIMESTAMP/DATE类型使用 setTimestamp 而非 setObject
|
||
|
||
7.5 Oracle类型到PostgreSQL映射(mapOracleTypeToPg / convertOracleTypeToPg)
|
||
VARCHAR2 → VARCHAR(n), NVARCHAR2 → VARCHAR(n)
|
||
CHAR → CHAR(n), NCHAR → CHAR(n)
|
||
NUMBER(p,s) → NUMERIC(p,s), NUMBER → NUMERIC
|
||
FLOAT → DOUBLE PRECISION
|
||
DATE → TIMESTAMP, TIMESTAMP → TIMESTAMP
|
||
CLOB → TEXT, BLOB → BYTEA, RAW → BYTEA
|
||
LONG → TEXT, LONG RAW → BYTEA
|
||
默认 → TEXT
|
||
|
||
7.6 同步策略创建(createTargetTables)
|
||
- 先删除同taskId的旧策略
|
||
- 对每个策略:
|
||
a. 获取源/目标数据源信息
|
||
b. 检查目标表是否已存在
|
||
c. 若不存在,生成建表DDL(支持Oracle和Oracle→PG两种模式)
|
||
d. 在目标库执行建表
|
||
e. 保存策略记录
|
||
|
||
7.7 Quartz任务管理
|
||
- 添加任务: saveAndScheduleJob → 创建QuartzJob,jobClassName固定为SyncDataJob
|
||
- 编辑任务: 编辑后重新调度
|
||
- 暂停: schedulerDelete + 更新状态为STATUS_DISABLE
|
||
- 恢复: schedulerDelete + 重新schedulerAdd + 更新状态为STATUS_NORMAL
|
||
- 立即执行: SimpleTrigger,0.1秒后执行一次
|
||
- 删除: schedulerDelete + removeById
|
||
|
||
|
||
八、重要VO类
|
||
--------------------------------------------------------------------------------
|
||
- DateRangeVO: minDate, maxDate(日期范围)
|
||
- IdRangeVO: minId, maxId(ID范围)
|
||
- MindMapVO: databaseName, List<UserInfoVO>(思维导图数据)
|
||
- UserInfoVO: userName, List<TableInfoVO>
|
||
- TableInfoVO: tableName, columnName
|
||
- TableColumnVO: columnName, typeName, columnSize, decimalDigits, isNullable, columnDef
|
||
- PieChartVO: name(表名), value(同步数), percent(百分比)
|
||
- SyncRecordVO: id, taskName, sourceName, targetName, startTime, endTime
|
||
- TaskHisStatsVO: taskName, syncNum
|
||
- TaskStatsResultVO: dateTimes(List<String>), taskStatsInfos(List<TaskStatsInfo>)
|
||
- TaskStatsInfo: taskName, taskStats(List<TaskStatsVO>)
|
||
- TaskStatsVO(base-core): id, taskName, dateTime, syncNum
|
||
|
||
|
||
九、代码风格与约定
|
||
--------------------------------------------------------------------------------
|
||
1. Controller层:
|
||
- 继承 JeecgController<Entity, Service>
|
||
- 使用 @Tag + @Operation 做Swagger文档
|
||
- 使用 @AutoLog 记录操作日志
|
||
- 返回统一 Result<T> 对象
|
||
- 分页查询使用 QueryGenerator.initQueryWrapper + MyBatis-Plus Page
|
||
|
||
2. Service层:
|
||
- 接口继承 IService<Entity>
|
||
- 实现类继承 ServiceImpl<Mapper, Entity>
|
||
- 使用 @RequiredArgsConstructor 或 @Autowired 注入
|
||
- 事务注解 @Transactional(rollbackFor = Exception.class)
|
||
|
||
3. 实体类:
|
||
- 使用 @TableName + @TableId(type = IdType.ASSIGN_ID)
|
||
- 日期字段使用 @JsonFormat + @DateTimeFormat
|
||
- 非数据库字段标记 @TableField(exist = false)
|
||
- 逻辑删除 @TableLogic
|
||
|
||
4. 异常处理:
|
||
- 业务异常统一抛出 JeecgBootException
|
||
- 数据库异常 SQLException 传播或包装
|
||
|
||
5. 数据库区分:
|
||
- Oracle: owner/table名使用大写 + 双引号, 条件使用 TO_DATE/TO_CHAR
|
||
- PostgreSQL: schema/table名使用小写 + 双引号, 条件使用 TIMESTAMP 字面量
|
||
|
||
|
||
十、已知注意事项与潜在问题
|
||
--------------------------------------------------------------------------------
|
||
1. StasTaskConfigServiceImpl.syncDataByFieldType 仅支持Oracle(isDateColumn写死了Oracle SQL),
|
||
而 SyncDataJob.syncDataByFieldType 支持Oracle+PG(通过dbType参数区分)。
|
||
两个类中存在大量重复的同步逻辑代码。
|
||
|
||
2. StasDataSourceServiceImpl.queryDatabaseMetadata 方法中,PostgreSQL数据源连接时
|
||
仍使用 ORACLE_DRIVER 而非 POSTGRES_DRIVER,可能存在Bug。
|
||
|
||
3. OracleSync 和 OracleToPgSync 是独立工具类(有main方法),不属于Spring容器管理,
|
||
数据库连接信息硬编码,仅用于一次性迁移脚本。
|
||
|
||
4. SyncDataJob 通过 @Resource 注入Mapper(因Quartz Job不由Spring直接管理实例),
|
||
需要Spring的Quartz集成支持依赖注入。
|
||
|
||
5. StasTaskConfigServiceImpl.getMindMap 使用 CompletableFuture.supplyAsync 但
|
||
使用默认线程池(ForkJoinPool),在高并发场景可能需要自定义线程池。
|
||
|
||
6. 同步策略的 createTargetTables 方法在事务中执行DDL操作(CREATE TABLE),
|
||
某些数据库驱动可能不支持DDL回滚。
|
||
|
||
7. syncByDateRange 中删除目标库数据的逻辑(deleteByEquals)在边界条件处理上
|
||
可能存在数据一致性问题(先删后插期间如有并发访问可能看到空数据)。
|
||
|
||
|
||
十一、模块间依赖关系
|
||
--------------------------------------------------------------------------------
|
||
jeecg-module-sync 依赖:
|
||
└── jeecg-boot-base-core
|
||
├── 实体类: StasDataSource, StasSyncStrategy, StasTaskConfig, StasSyncLog,
|
||
│ StasSyncNum, StasSyncRecord, QuartzJob
|
||
├── Mapper: StasDataSourceMapper, StasSyncStrategyMapper, StasTaskConfigMapper,
|
||
│ StasSyncLogMapper, StasSyncNumMapper, StasSyncRecordMapper, QuartzJobMapper
|
||
├── VO: TaskStatsVO
|
||
├── 枚举: SourceDataTypeEnum, SyncTaskStatusEnum
|
||
├── 常量: QuartzJobConstant, CommonConstant
|
||
├── 工具: DBUtil, DateUtils
|
||
└── 基础: JeecgController, Result, QueryGenerator, JeecgBootException
|
||
|
||
外部依赖(通过 jeecg-boot-base-core 间接引入):
|
||
- MyBatis-Plus (分页、条件构造、CRUD)
|
||
- Quartz Scheduler (定时任务)
|
||
- Swagger/OpenAPI (API文档)
|
||
- Lombok (代码简化)
|
||
- Apache Commons Lang (StringUtils)
|
||
- Oracle JDBC Driver / PostgreSQL JDBC Driver
|
||
|
||
|
||
十二、SQL数据库表结构参考
|
||
--------------------------------------------------------------------------------
|
||
核心表(定义在 db/stas.sql 中):
|
||
- stas_data_source: 数据源配置表
|
||
- stas_sync_strategy: 同步策略表
|
||
- stas_task_config: 任务配置表
|
||
- stas_sync_log: 同步日志表
|
||
- stas_sync_num: 同步数量统计表
|
||
- stas_sync_record: 同步记录表
|
||
|
||
Quartz表(定义在 db/stas.sql 或 Quartz默认脚本中):
|
||
- sys_quartz_job: 定时任务表
|
||
|
||
================================================================================
|
||
文件生成时间: 2026-05-09
|
||
适用于: AI辅助代码编辑上下文参考
|
||
================================================================================
|
||
|