refactor(model): 重构模型类包结构并优化序列化处理

重构模型类包结构,将模型类按功能模块划分到不同的子包中。优化序列化处理,为VO类添加serialVersionUID并实现Serializable接口。移除部分冗余的serialVersionUID字段,简化模型类代码。同时修复UITools中空值处理的问题,并更新pom版本至0.0.100-SNAPSHOT。

- 将模型类按功能模块划分到ds子包中
- 为VO类添加序列化支持
- 移除冗余的serialVersionUID字段
- 修复UITools空值处理问题
- 更新项目版本号
This commit is contained in:
2025-10-09 18:27:48 +08:00
parent 51b8c16798
commit c4eec0a9dd
457 changed files with 8426 additions and 3669 deletions

View File

@@ -1,11 +1,13 @@
# Server模块Service缓存调整为Vo对象对齐文档
# 6A工作流 - ALIGNMENT阶段文档
## 任务名称Server模块Service缓存调整为Vo对象
## 1. 项目上下文分析
### 1.1 项目结构与技术栈
- **项目**: Contract-Manager
- **模块**: server模块
- **技术栈**: Java 21, Spring Boot 3.3.7, Spring Data JPA 3.3.7, Redis (用于缓存)
- **技术栈**: Java 21, Spring Boot 3.3.7, Spring Data JPA 3.3.7, Redis (用于缓存), Lombok 1.18.32
### 1.2 现有代码模式
- **接口结构**: IEntityService<T>接口定义了基础的CRUD操作泛型T当前用于指定实体类类型
@@ -15,10 +17,16 @@
- **缓存问题**: 当前使用实体类进行缓存由于Hibernate代理对象序列化问题可能导致懒加载异常
- **实体类和Vo类**: 都定义在 common 模块中,确保在不同模块之间的引用和使用
### 1.3 架构模式
- 采用经典的三层架构Controller层、Service层、Repository层
- Service层同时承担业务逻辑和数据转换职责
- 使用Spring Data JPA进行数据访问
- 使用Redis作为缓存层提高系统性能
## 2. 需求理解确认
### 2.1 原始需求
> server模块中注解了 @CacheConfig的Service调整接口泛型参数涉及到Service上各个方法的修改,方法修改相关引用方法的地方也要修改
> server模块中注解了 @CacheConfig的Service调整接口泛型参数涉及到Service上各个方法的修改方法修改相关引用方法的地方也要修改
### 2.1.1 扩展需求
> 使用VO替代实体缓存因为使用redis服务需要避免代理对象序列化彻底规避懒加载问题
@@ -37,7 +45,7 @@
### 2.3 需求理解
- 当前Service类同时实现`IEntityService<Entity>``QueryService<Vo>`接口,还需实现`VoableService<Entity, Vo>`接口
- 需要调整Service类的接口实现使IEntityService保持使用实体类类型QueryService使用Vo类型
- Service类需要同时实现IEntityService<实体类>和QueryService<Vo类>接口,并根据不同接口的要求实现对应的方法,IEntityService和QueryService接口有同名的方法按各自结构定义实现
- Service类需要同时实现IEntityService<实体类>和QueryService<Vo类>接口,并根据不同接口的要求实现对应的方法IEntityService和QueryService接口有同名的方法按各自结构定义实现
- 需要确保缓存注解的键值表达式仍然有效
- 需要保证修改后系统功能正常运行
- 使用VO替代实体类进行缓存避免Hibernate代理对象序列化问题彻底规避懒加载异常
@@ -46,8 +54,7 @@
1. **数据转换问题**: 如何处理从实体类到VO的转换和从VO到实体类的转换
- 实体类应该实现Voable接口提供toVo方法实现从实体类到VO的转换
- Service类实现VoableService接口提供updateByVo方法实现从Vo到实体类的转换,参考 ProjectQuotationServiceupdateByVo方法
- Service类实现VoableService接口提供updateByVo方法实现从Vo到实体类的转换参考ProjectQuotationServiceupdateByVo方法
2. **缓存键表达式**: 修改泛型后,缓存注解中的键表达式(如@CacheEvict(key = "#p0.id"))是否需要修改?
- 需要确认VO类是否与实体类具有相同的属性结构
@@ -61,45 +68,8 @@
5. **查询规范**: getSpecification方法如何适配从Entity到Vo的转换
- 解决方案Service类同时实现IEntityService<实体类>和QueryService<Vo类>接口
- 在IEntityService<实体类>接口中保持getSpecification方法返回基于JPA实体的Specification
```java
public Page<CompanyExtendInfo> findAll(Specification<CompanyExtendInfo> spec, Pageable pageable) {
return repository.findAll(spec, pageable);
}
```
- 在QueryService<Vo类>接口的findAll方法中先使用基于实体类的Specification查询数据然后通过map操作将实体转换为Vo
```java
@Override
public Page<ProjectCostVo> findAll(JsonNode paramsNode, Pageable pageable) {
Specification<ProjectCost> spec = null;
if (paramsNode.has(ServiceConstant.KEY_SEARCH_TEXT)) {
spec = getSpecification(paramsNode.get(ServiceConstant.KEY_SEARCH_TEXT).asText());
}
// field
spec = SpecificationUtils.andParam(spec, paramsNode, "project");
if (paramsNode.has("project.customer")) {
Integer customerId = paramsNode.get("project.customer").asInt();
spec = SpecificationUtils.and(spec, (root, query, builder) -> {
return builder.equal(root.get("project").get("customer").get("id"), customerId);
});
}
Page<ProjectCost> page = findAll(spec, pageable);
return page.map(ProjectCost::toVo);
}
```
- 实体类实现Voable<Vo类>接口提供toVo方法进行转换
```java
@Cacheable(key = "#p0")
@Override
public ProjectCostVo findById(Integer id) {
ProjectCost cost = getById(id);
if (cost != null) {
return cost.toVo();
}
return null;
}
```
6. **缓存对象转换**: 如何确保缓存中存储的是VO对象而不是实体类对象
解决方案通过以下机制确保缓存中存储VO对象
@@ -107,16 +77,6 @@ public Page<CompanyExtendInfo> findAll(Specification<CompanyExtendInfo> spec, Pa
- QueryService接口的方法如findById添加@Cacheable注解
- 在这些缓存方法的实现中查询实体后通过调用实体类的toVo()方法转换为Vo对象再返回
- 实体类实现Voable接口提供toVo()方法进行转换
- 示例实现:
```java
@Cacheable(key = "#id")
@Override
public CompanyFileTypeLocalVo findById(Integer id) {
Optional<CompanyFileTypeLocal> optional = repository.findById(id);
return optional.map(CompanyFileTypeLocal::toVo).orElse(null);
}
```
这种方式确保了缓存中存储的是转换后的Vo对象而不是原始实体对象。
7. **WebSocket服务影响**: WebSocketServerCallbackManager类直接调用IEntityService接口由于我们保持IEntityService泛型为实体类因此对WebSocket服务的影响较小
- WebSocketServerCallbackManager类中的createNewEntity、findEntityTypeInInterfaces等方法主要依赖于IEntityService的实体类泛型