================================================================================ 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: userName, List - 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), taskStatsInfos(List) - TaskStatsInfo: taskName, taskStats(List) - TaskStatsVO(base-core): id, taskName, dateTime, syncNum 九、代码风格与约定 -------------------------------------------------------------------------------- 1. Controller层: - 继承 JeecgController - 使用 @Tag + @Operation 做Swagger文档 - 使用 @AutoLog 记录操作日志 - 返回统一 Result 对象 - 分页查询使用 QueryGenerator.initQueryWrapper + MyBatis-Plus Page 2. Service层: - 接口继承 IService - 实现类继承 ServiceImpl - 使用 @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辅助代码编辑上下文参考 ================================================================================