# 部门同步服务重构说明 ## 重构概述 将部门同步功能重构为**数据查询**和**数据同步**两个独立的服务,实现职责分离和灵活性提升。 --- ## 架构变化 ### 重构前 ``` ┌─────────────────────────────────────────┐ │ DepartmentSyncServiceImpl │ │ │ │ ┌─────────────────────────────────┐ │ │ │ syncBranchDepartments() │ │ │ │ ├─ 查询 SQL Server │ │ │ │ └─ 写入 MySQL │ │ │ └─────────────────────────────────┘ │ └─────────────────────────────────────────┘ ``` **问题**: - ❌ 数据查询和同步逻辑耦合 - ❌ 无法使用外部数据源 - ❌ 难以扩展其他数据来源 ### 重构后 ``` ┌──────────────────────────────────────────────────────────┐ │ DepartmentSyncDataServiceImpl (新增) │ │ 职责:从 SQL Server 查询数据 │ │ │ │ ├─ getBranchDepartments() │ │ └─ 返回 List │ └──────────────────────────────────────────────────────────┘ │ v ┌──────────────────────────────────────────────────────────┐ │ DepartmentSyncServiceImpl (重构) │ │ 职责:接收数据并写入 MySQL │ │ │ │ ├─ syncBranchDepartments() │ │ │ └─ 调用 DepartmentSyncDataService 获取数据 │ │ │ │ │ └─ syncBranchDepartments(List) │ │ └─ 接收外部传入的数据进行同步 │ └──────────────────────────────────────────────────────────┘ ``` **优势**: - ✅ 职责单一,易于维护 - ✅ 支持外部数据源 - ✅ 灵活性高,易于扩展 --- ## 核心组件 ### 1. IDepartmentSyncDataService(新增) **文件路径**: `ruoyi-system/src/main/java/com/ruoyi/system/service/IDepartmentSyncDataService.java` **职责**: 定义从 SQL Server 查询数据的接口 ```java public interface IDepartmentSyncDataService { /** * 从 SQL Server 查询合作单位下的所有分公司数据 * * @return 分公司列表 */ List getBranchDepartments(); } ``` --- ### 2. DepartmentSyncDataServiceImpl(新增) **文件路径**: `ruoyi-system/src/main/java/com/ruoyi/system/service/impl/DepartmentSyncDataServiceImpl.java` **职责**: 专门负责从 SQL Server 查询部门数据 **关键特性**: ```java @Service public class DepartmentSyncDataServiceImpl implements IDepartmentSyncDataService { @Autowired private DepartmentSyncMapper departmentSyncMapper; // 带 @DataSource 注解 @Override public List getBranchDepartments() { log.info("开始从 SQL Server 查询分公司数据..."); // 自动切换到 SQL Server 数据源 List branchDepts = departmentSyncMapper.selectBranchDepartments(); log.info("从 SQL Server 查询到 {} 条分公司数据", branchDepts.size()); return branchDepts; } } ``` **数据流**: ``` DepartmentSyncDataServiceImpl ↓ DepartmentSyncMapper (@DataSource(SQLSERVER)) ↓ SQL Server 数据库 (uv_department) ↓ 返回 List ``` --- ### 3. IDepartmentSyncService(重构) **文件路径**: `ruoyi-system/src/main/java/com/ruoyi/system/service/IDepartmentSyncService.java` **变化**: 新增重载方法,支持外部数据源 ```java public interface IDepartmentSyncService { /** * 同步分公司和部门数据(从 SQL Server 查询并同步到 MySQL) */ AjaxResult syncBranchDepartments(); /** * 同步分公司和部门数据(使用外部传入的数据源) * * @param branchDepts 外部传入的分公司数据列表 */ AjaxResult syncBranchDepartments(List branchDepts); } ``` --- ### 4. DepartmentSyncServiceImpl(重构) **文件路径**: `ruoyi-system/src/main/java/com/ruoyi/system/service/impl/DepartmentSyncServiceImpl.java` **变化**: 1. 移除对 `DepartmentSyncMapper` 的直接依赖 2. 注入 `IDepartmentSyncDataService` 获取数据 3. 新增 `syncBranchDepartments(List)` 方法 **重构后的代码**: ```java @Service public class DepartmentSyncServiceImpl implements IDepartmentSyncService { @Autowired private IDepartmentSyncDataService departmentSyncDataService; // 数据查询服务 @Autowired private SysDeptMapper sysDeptMapper; // MySQL 操作 // 方法 1: 内部查询 + 同步 @Override @Transactional public AjaxResult syncBranchDepartments() { // 调用数据查询服务获取 SQL Server 数据 List branchDepts = departmentSyncDataService.getBranchDepartments(); if (branchDepts == null || branchDepts.isEmpty()) { return AjaxResult.warn("未获取到需要同步的分公司数据"); } // 调用重载方法执行同步 return syncBranchDepartments(branchDepts); } // 方法 2: 外部数据源 + 同步(新增) @Override @Transactional public AjaxResult syncBranchDepartments(List branchDepts) { if (branchDepts == null || branchDepts.isEmpty()) { return AjaxResult.warn("传入的部门数据为空"); } log.info("开始同步 {} 条分公司数据到 MySQL 数据库...", branchDepts.size()); // 同步逻辑(只涉及 MySQL 操作) // ... } } ``` **数据流**: #### 流程 1: 内部查询 + 同步 ``` syncBranchDepartments() ↓ 调用 departmentSyncDataService.getBranchDepartments() ↓ 获取 List ↓ 调用 syncBranchDepartments(List) ↓ 写入 MySQL 数据库 ``` #### 流程 2: 外部数据源 + 同步 ``` 外部调用者提供 List ↓ syncBranchDepartments(List) ↓ 写入 MySQL 数据库 ``` --- ### 5. DepartmentSyncController(更新) **文件路径**: `ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/DepartmentSyncController.java` **变化**: 新增接口支持外部数据源 ```java @RestController @RequestMapping("/system/dept/sync") public class DepartmentSyncController { @Autowired private IDepartmentSyncService departmentSyncService; /** * 接口 1: 同步分公司和部门数据(从 SQL Server 查询并同步) */ @PostMapping("/branch") public AjaxResult syncBranchDepartments() { return departmentSyncService.syncBranchDepartments(); } /** * 接口 2: 同步分公司和部门数据(使用外部传入的数据源) */ @PostMapping("/branch/data") public AjaxResult syncBranchDepartmentsWithData(@RequestBody List branchDepts) { return departmentSyncService.syncBranchDepartments(branchDepts); } } ``` --- ## 使用场景 ### 场景 1: 常规同步(从 SQL Server 查询) ```bash POST http://localhost:8080/system/dept/sync/branch ``` **执行流程**: 1. Controller 调用 `departmentSyncService.syncBranchDepartments()` 2. Service 调用 `departmentSyncDataService.getBranchDepartments()` 3. 自动切换到 SQL Server 查询数据 4. 将数据写入 MySQL --- ### 场景 2: 使用外部数据源 ```bash POST http://localhost:8080/system/dept/sync/branch/data Content-Type: application/json [ { "departmentId": 1001, "departmentName": "湛江--护士", "parentId": 100, "parentName": "合作单位" }, { "departmentId": 1002, "departmentName": "湛江--车队", "parentId": 100, "parentName": "合作单位" } ] ``` **执行流程**: 1. Controller 接收 JSON 数据并转换为 `List` 2. Controller 调用 `departmentSyncService.syncBranchDepartments(branchDepts)` 3. Service 直接将数据写入 MySQL --- ### 场景 3: 从其他系统获取数据后同步 ```java @Service public class CustomSyncService { @Autowired private IDepartmentSyncService departmentSyncService; public void syncFromExternalSystem() { // 1. 从其他系统获取数据(如 HTTP API、消息队列等) List externalData = fetchDataFromExternalSystem(); // 2. 进行数据预处理 List processedData = preprocessData(externalData); // 3. 调用同步服务 AjaxResult result = departmentSyncService.syncBranchDepartments(processedData); log.info("同步结果: {}", result.get("msg")); } } ``` --- ### 场景 4: 批量同步多个数据源 ```java @Service public class BatchSyncService { @Autowired private IDepartmentSyncDataService departmentSyncDataService; @Autowired private IDepartmentSyncService departmentSyncService; public void batchSync() { // 1. 从 SQL Server 获取数据 List sqlServerData = departmentSyncDataService.getBranchDepartments(); // 2. 从其他来源获取数据 List otherData = getDataFromOtherSource(); // 3. 合并数据 List allData = new ArrayList<>(); allData.addAll(sqlServerData); allData.addAll(otherData); // 4. 统一同步 departmentSyncService.syncBranchDepartments(allData); } } ``` --- ## 接口对比 | 接口 | 路径 | 数据来源 | 适用场景 | |------|------|----------|----------| | **接口 1** | `POST /system/dept/sync/branch` | 内部查询 SQL Server | 常规定时同步 | | **接口 2** | `POST /system/dept/sync/branch/data` | 外部传入 JSON | 手动数据导入、数据预处理、多源整合 | --- ## 定时任务更新 定时任务可以继续使用原有方式,无需修改: ```java @Component("oaSyncTask") public class OaSyncTask { @Autowired private IDepartmentSyncService departmentSyncService; public void syncOaData() { // 自动从 SQL Server 查询并同步 AjaxResult result = departmentSyncService.syncBranchDepartments(); log.info("定时同步结果: {}", result.get("msg")); } } ``` --- ## 优势总结 ### 1. 职责分离 ✅ - **DepartmentSyncDataService**: 只负责查询数据 - **DepartmentSyncService**: 只负责同步数据 ### 2. 灵活性提升 ✅ - 支持从 SQL Server 查询 - 支持外部数据源 - 支持数据预处理 - 支持多源数据整合 ### 3. 易于扩展 ✅ ```java // 扩展:支持其他数据源 public interface IDepartmentSyncDataService { List getBranchDepartments(); // SQL Server List getBranchDepartmentsFromOracle(); // Oracle List getBranchDepartmentsFromAPI(); // HTTP API } ``` ### 4. 易于测试 ✅ ```java @Test public void testSyncWithMockData() { // 创建测试数据 List testData = createTestData(); // 测试同步逻辑 AjaxResult result = departmentSyncService.syncBranchDepartments(testData); // 验证结果 assertEquals(200, result.get("code")); } ``` --- ## 迁移指南 ### 对于现有代码 **无需修改**!原有调用方式完全兼容: ```java // 原有代码 departmentSyncService.syncBranchDepartments(); // 仍然有效,行为不变 ``` ### 对于新功能 使用新增的重载方法: ```java // 新功能:使用外部数据源 List externalData = getExternalData(); departmentSyncService.syncBranchDepartments(externalData); ``` --- ## 文件清单 ### 新增文件 | 文件 | 说明 | |------|------| | `IDepartmentSyncDataService.java` | 数据查询服务接口 | | `DepartmentSyncDataServiceImpl.java` | 数据查询服务实现 | ### 修改文件 | 文件 | 变化 | |------|------| | `IDepartmentSyncService.java` | 新增重载方法 | | `DepartmentSyncServiceImpl.java` | 重构实现,支持外部数据源 | | `DepartmentSyncController.java` | 新增接口 `/branch/data` | ### 无需修改 | 文件 | 说明 | |------|------| | `DepartmentSyncMapper.java` | Mapper 接口不变 | | `DepartmentSyncMapper.xml` | SQL 映射不变 | | `OaSyncTask.java` | 定时任务不变 | --- ## 总结 通过本次重构,实现了: ✅ **职责分离**: 数据查询和同步逻辑解耦 ✅ **灵活性提升**: 支持多种数据来源 ✅ **易于扩展**: 可轻松添加新的数据源 ✅ **向后兼容**: 原有代码无需修改 ✅ **易于测试**: 可使用 Mock 数据进行单元测试 --- ## 相关文档 - [OA数据同步多数据源架构说明.md](OA数据同步多数据源架构说明.md) - [多数据源切换问题修复说明.md](多数据源切换问题修复说明.md) - [SQL Server数据源查询优化说明.md](SQL Server数据源查询优化说明.md)