refactor(service): 统一Service缓存为VO对象并优化关联实体处理

重构Service类实现,将QueryService泛型参数调整为VO类型,确保缓存VO对象而非实体。优化关联实体处理逻辑,减少重复代码。修改findById方法返回VO对象,新增getById方法获取实体。更新相关调用点以适配新接口。

调整WebSocket处理、控制器及Service实现,确保数据类型一致性。完善文档记录重构过程及发现的问题。为后续优化提供基础架构支持。
This commit is contained in:
2025-09-29 19:31:51 +08:00
parent 64471b46f8
commit 49413ad473
167 changed files with 6840 additions and 1811 deletions

View File

@@ -0,0 +1,178 @@
# Service类结构模式分析报告
## 1. 概述
本报告是"实体-VO转换机制与缓存策略任务拆分"子任务1的延伸分析旨在详细分析Contract-Manager项目中Service类的实现模式特别是QueryService接口泛型参数的使用情况为将Server模块Service缓存从实体对象调整为VO对象提供具体的修改依据。
## 2. Service类实现模式分析
通过对Server模块中Service类的分析发现了两种主要的实现模式
### 2.1 模式一正确实现模式VO优先
这种模式下Service类实现QueryService接口时使用VO类型作为泛型参数符合项目设计理念。
**示例代码:**
```java
@Service
@CacheConfig(cacheNames = "inventory")
public class InventoryService
implements IEntityService<Inventory>, QueryService<InventoryVo>, VoableService<Inventory, InventoryVo> {
// Service方法实现
}
@Service
@CacheConfig(cacheNames = "function")
public class FunctionService implements IEntityService<Function>, QueryService<FunctionVo>, VoableService<Function, FunctionVo> {
@Cacheable(key = "#p0")
public FunctionVo findById(Integer id) {
return repository.findById(id).map(Function::toVo).orElse(null);
}
}
```
**特点:**
1. QueryService接口使用VO类型作为泛型参数
2. findById等缓存方法返回VO对象
3. findAll方法通常使用map(Entity::toVo)转换为VO对象
4. 缓存的是VO对象符合设计要求
**采用此模式的Service类**
- InventoryService
- ProjectQuotationService
- FunctionService
- DepartmentService
- BankService
- ContractBidVendorService
- ProjectIndustryService
- ProjectBidService
- ProjectFundPlanService
- InventoryHistoryPriceService
- ProjectTypeService
- PermissionService
- ProjectCostItemService
- EmployeeRoleService
- CustomerSatisfactionSurveyService
### 2.2 模式二:错误实现模式(实体优先)
这种模式下Service类实现QueryService接口时使用实体类型作为泛型参数不符合项目设计理念。
**示例代码:**
```java
@Service
@CacheConfig(cacheNames = "company")
public class CompanyService extends EntityService<Company, Integer>
implements IEntityService<Company>, QueryService<Company>, VoableService<Company, CompanyVo> {
// Service方法实现
}
@Service
public class CompanyBlackReasonService implements IEntityService<CompanyBlackReason>, QueryService<CompanyBlackReason>,
VoableService<CompanyBlackReason, CompanyBlackReasonVo> {
// Service方法实现
}
```
**特点:**
1. QueryService接口使用实体类型作为泛型参数
2. findById等缓存方法返回实体对象
3. 缓存的是实体对象,不符合设计要求
4. 虽然同时实现了VoableService接口但转换逻辑与缓存逻辑分离
**采用此模式的Service类**
- CompanyService
- CompanyBlackReasonService
- ContractPayPlanService
- CompanyOldNameService
- CompanyCustomerEntityService
- ContractCatalogService
- CompanyInvoiceInfoService
- CompanyExtendInfoService
## 3. WebSocketServerCallbackManager分析
WebSocketServerCallbackManager类负责处理客户端与服务器之间的WebSocket通信包括对查询服务的调用处理
```java
private Object invokerFindByIdMethod(Object service, JsonNode argumentsNode) {
JsonNode paramsNode = argumentsNode.get(0);
if (service instanceof IEntityService<?> entityService) {
Integer id = paramsNode.asInt();
return entityService.getById(id);
}
// 其他实现...
}
private Object invokerFindAllMethod(Object service, JsonNode argumentsNode) throws JsonProcessingException {
JsonNode paramsNode = argumentsNode.get(0);
JsonNode pageableNode = argumentsNode.get(1);
PageArgument pageArgument = objectMapper.treeToValue(pageableNode, PageArgument.class);
QueryService<?> entityService = (QueryService<?>) service;
Page<?> page = entityService.findAll(paramsNode, pageArgument.toPageable());
return PageContent.of(page.map(entity -> {
if (entity instanceof Voable<?>) {
return ((Voable<?>) entity).toVo();
}
return entity;
}));
}
```
**关键点:**
1. invokerFindByIdMethod直接返回实体对象没有进行VO转换
2. invokerFindAllMethod在返回前会尝试将实体转换为VO
3. 这种不一致的处理方式可能导致客户端接收的数据类型不一致
## 4. 缓存策略分析
### 4.1 正确的缓存策略(模式一)
```java
@Cacheable(key = "#p0")
public FunctionVo findById(Integer id) {
return repository.findById(id).map(Function::toVo).orElse(null);
}
```
**特点:**
1. 缓存方法直接返回VO对象
2. 在缓存方法内部完成实体到VO的转换
3. 缓存的是VO对象符合设计要求
### 4.2 错误的缓存策略(模式二)
```java
@Cacheable(key = "#id")
public Contract findById(Integer id) {
// 直接返回实体对象
}
```
**特点:**
1. 缓存方法返回实体对象
2. 缓存的是实体对象,不符合设计要求
3. 客户端可能需要额外的转换步骤
## 5. 需要修改的Service类清单
基于以上分析以下是需要修改的Service类清单
| Service类名 | 问题 | 修改建议 |
|------------|------|---------|
| CompanyService | QueryService使用实体类型 | 将QueryService<Company>改为QueryService<CompanyVo> |
| CompanyBlackReasonService | QueryService使用实体类型 | 将QueryService<CompanyBlackReason>改为QueryService<CompanyBlackReasonVo> |
| ContractPayPlanService | QueryService使用实体类型 | 将QueryService<ContractPayPlan>改为QueryService<ContractPayPlanVo> |
| CompanyOldNameService | QueryService使用实体类型 | 将QueryService<CompanyOldName>改为QueryService<CompanyOldNameVo> |
| CompanyCustomerEntityService | QueryService使用实体类型 | 将QueryService<CompanyCustomerEntity>改为QueryService<CompanyCustomerEntityVo> |
| ContractCatalogService | QueryService使用实体类型 | 将QueryService<ContractCatalog>改为QueryService<ContractCatalogVo> |
| CompanyInvoiceInfoService | QueryService使用实体类型 | 将QueryService<CompanyInvoiceInfo>改为QueryService<CompanyInvoiceInfoVo> |
| CompanyExtendInfoService | QueryService使用实体类型 | 将QueryService<CompanyExtendInfo>改为QueryService<CompanyExtendInfoVo> |
## 6. 结论
通过对Service类实现模式的详细分析我们明确了需要修改的Service类清单和具体的修改建议。这些修改将有助于统一Service类的实现模式确保缓存的是VO对象而不是实体对象从而提高系统的一致性和性能。
本报告为后续的子任务提供了具体的修改依据,帮助确定具体的实现方案和步骤。