refactor(service): 统一Service缓存为VO对象并优化关联实体处理
重构Service类实现,将QueryService泛型参数调整为VO类型,确保缓存VO对象而非实体。优化关联实体处理逻辑,减少重复代码。修改findById方法返回VO对象,新增getById方法获取实体。更新相关调用点以适配新接口。 调整WebSocket处理、控制器及Service实现,确保数据类型一致性。完善文档记录重构过程及发现的问题。为后续优化提供基础架构支持。
This commit is contained in:
@@ -0,0 +1,221 @@
|
||||
# 实体-VO转换机制与缓存策略实现分析报告
|
||||
|
||||
## 1. 概述
|
||||
|
||||
本报告是"实体-VO转换机制与缓存策略任务拆分"子任务1的执行结果,旨在分析Contract-Manager项目中实体-VO转换机制和Service类结构,为将Server模块Service缓存从实体对象调整为VO对象提供基础分析。
|
||||
|
||||
## 2. 核心接口体系分析
|
||||
|
||||
### 2.1 Voable接口
|
||||
|
||||
`Voable<T>`是实体类实现的核心接口,用于将实体转换为VO对象:
|
||||
|
||||
```java
|
||||
public interface Voable<T> {
|
||||
/**
|
||||
* 转换为Vo
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
T toVo();
|
||||
}
|
||||
```
|
||||
|
||||
该接口非常简洁,只定义了一个`toVo()`方法,用于将实体对象转换为对应的VO对象。
|
||||
|
||||
### 2.2 QueryService接口
|
||||
|
||||
`QueryService<Vo>`是查询服务接口,提供通用的分页查询能力:
|
||||
|
||||
```java
|
||||
public interface QueryService<Vo> {
|
||||
/**
|
||||
* 根据ID查询单条数据
|
||||
* @param id
|
||||
* @return 符合ID的Vo对象,若不存在则返回null
|
||||
*/
|
||||
Vo findById(Integer id);
|
||||
|
||||
/**
|
||||
* 根据查询参数和分页条件获取数据列表
|
||||
*
|
||||
* @param paramsNode JSON格式的查询参数节点,包含各种过滤条件
|
||||
* @param pageable 分页参数,包含页码、每页条数、排序规则等信息
|
||||
* @return 分页查询结果,包含符合条件的数据列表和分页元数据
|
||||
*/
|
||||
Page<Vo> findAll(JsonNode paramsNode, Pageable pageable);
|
||||
|
||||
/**
|
||||
* 根据查询参数统计符合条件的数据总数
|
||||
* @param paramsNode JSON格式的查询参数节点,包含各种过滤条件
|
||||
* @return 符合条件的数据总数
|
||||
*/
|
||||
default long count(JsonNode paramsNode) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
该接口的泛型参数`Vo`表示查询结果的数据类型,即View Object类,是可序列化、可持久的类。
|
||||
|
||||
### 2.3 VoableService接口
|
||||
|
||||
`VoableService<M, Vo>`是可转换为VO的服务接口:
|
||||
|
||||
```java
|
||||
public interface VoableService<M, Vo> {
|
||||
void updateByVo(M model, Vo vo);
|
||||
}
|
||||
```
|
||||
|
||||
该接口定义了一个`updateByVo()`方法,用于根据VO对象更新对应的实体对象。
|
||||
|
||||
### 2.4 IEntityService接口
|
||||
|
||||
`IEntityService<T>`是实体服务接口,提供基础的CRUD操作:
|
||||
|
||||
```java
|
||||
public interface IEntityService<T> {
|
||||
T getById(Integer id);
|
||||
Page<T> findAll(Specification<T> specification, Pageable pageable);
|
||||
Specification<T> getSpecification(String searchText);
|
||||
List<T> search(String searchText);
|
||||
void delete(T entity);
|
||||
T save(T entity);
|
||||
}
|
||||
```
|
||||
|
||||
## 3. 实体-VO转换机制分析
|
||||
|
||||
以`Contract`实体和`ContractVo`为例,分析实体-VO转换机制:
|
||||
|
||||
### 3.1 实体类结构
|
||||
|
||||
`Contract`实体类实现了`Voable<ContractVo>`接口,表示它可以转换为`ContractVo`对象:
|
||||
|
||||
```java
|
||||
public class Contract
|
||||
implements IdentityEntity, NamedEntity, BasedEntity, CompanyBasedEntity, Serializable, Voable<ContractVo> {
|
||||
// 实体属性定义
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 VO类结构
|
||||
|
||||
`ContractVo`是一个简单的POJO类,使用`@Data`注解简化代码:
|
||||
|
||||
```java
|
||||
@Data
|
||||
public class ContractVo implements IdentityEntity, NamedEntity, CompanyBasedVo, ProjectBasedVo {
|
||||
// VO属性定义
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### 3.3 转换实现
|
||||
|
||||
`Contract`类实现了`toVo()`方法,用于将实体转换为VO:
|
||||
|
||||
```java
|
||||
@Override
|
||||
public ContractVo toVo() {
|
||||
ContractVo vo = new ContractVo();
|
||||
vo.setId(id);
|
||||
vo.setGuid(getGuid());
|
||||
vo.setCode(getCode());
|
||||
vo.setName(name);
|
||||
if (getCompany() != null) {
|
||||
vo.setCompanyId(getCompany().getId());
|
||||
}
|
||||
if (group != null) {
|
||||
vo.setGroupId(group.getId());
|
||||
}
|
||||
// ... 其他属性转换 ...
|
||||
return vo;
|
||||
}
|
||||
```
|
||||
|
||||
转换实现遵循以下模式:
|
||||
1. 创建对应的VO对象
|
||||
2. 将实体的基本属性直接复制到VO对象
|
||||
3. 对于关联实体,只复制其ID而不是整个对象
|
||||
4. 返回填充好的VO对象
|
||||
|
||||
## 4. Service类结构与缓存策略分析
|
||||
|
||||
### 4.1 Service类继承关系
|
||||
|
||||
以`ContractService`为例,Service类通常继承自`EntityService`并实现多个接口:
|
||||
|
||||
```java
|
||||
@Service
|
||||
@CacheConfig(cacheNames = "contract")
|
||||
public class ContractService extends EntityService<Contract, Integer> implements QueryService<Contract>, VoableService<Contract, ContractVo> {
|
||||
// Service方法实现
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### 4.2 缓存配置
|
||||
|
||||
Service类使用`@CacheConfig`注解配置缓存名称:
|
||||
|
||||
```java
|
||||
@CacheConfig(cacheNames = "contract")
|
||||
```
|
||||
|
||||
在Server模块中,共有58个Service类使用了`@CacheConfig`注解配置缓存。
|
||||
|
||||
### 4.3 缓存使用
|
||||
|
||||
查询方法通常使用`@Cacheable`注解缓存结果:
|
||||
|
||||
```java
|
||||
@Cacheable(key = "#id")
|
||||
public Contract findById(Integer id) {
|
||||
// 实现逻辑
|
||||
}
|
||||
```
|
||||
|
||||
增删改方法通常使用`@Caching`等注解清除缓存:
|
||||
|
||||
```java
|
||||
@Caching(evict = {
|
||||
@CacheEvict(key = "#contract.id"),
|
||||
@CacheEvict(cacheNames = "contract", key = "'findByCode_'.concat(#contract.code)")
|
||||
})
|
||||
public Contract save(Contract contract) {
|
||||
// 实现逻辑
|
||||
}
|
||||
```
|
||||
|
||||
## 5. 发现的问题和改进点
|
||||
|
||||
### 5.1 缓存对象类型不一致
|
||||
|
||||
目前,部分Service类的缓存对象是实体对象,而不是VO对象,这与项目的设计理念不一致。
|
||||
|
||||
### 5.2 泛型参数使用不一致
|
||||
|
||||
部分Service类实现的`QueryService`接口泛型参数是实体类型,而不是VO类型。
|
||||
|
||||
### 5.3 转换逻辑重复
|
||||
|
||||
每个实体类都需要实现`toVo()`方法,存在大量重复代码。
|
||||
|
||||
### 5.4 关联实体处理
|
||||
|
||||
当前的转换逻辑对于关联实体只复制ID,可能无法满足复杂查询的需求。
|
||||
|
||||
## 6. 结论
|
||||
|
||||
通过分析,我们了解了Contract-Manager项目中的实体-VO转换机制和Service类结构。目前的实现存在一些不一致性和改进空间,特别是在缓存对象类型和泛型参数使用方面。
|
||||
|
||||
为了将Server模块Service缓存从实体对象调整为VO对象,我们需要:
|
||||
1. 统一Service类实现的接口泛型参数
|
||||
2. 修改缓存注解,确保缓存的是VO对象而不是实体对象
|
||||
3. 优化转换逻辑,减少重复代码
|
||||
4. 处理好关联实体的转换和缓存
|
||||
|
||||
本报告为后续的子任务提供了基础分析,帮助确定具体的实现方案和步骤。
|
||||
Reference in New Issue
Block a user