Files
contract-manager/docs/task/server模块service缓存调整为Vo对象/ANALYSIS_entity_vo_conversion_implementation.md
songqq 49413ad473 refactor(service): 统一Service缓存为VO对象并优化关联实体处理
重构Service类实现,将QueryService泛型参数调整为VO类型,确保缓存VO对象而非实体。优化关联实体处理逻辑,减少重复代码。修改findById方法返回VO对象,新增getById方法获取实体。更新相关调用点以适配新接口。

调整WebSocket处理、控制器及Service实现,确保数据类型一致性。完善文档记录重构过程及发现的问题。为后续优化提供基础架构支持。
2025-09-29 19:31:51 +08:00

6.0 KiB
Raw Permalink Blame History

实体-VO转换机制与缓存策略实现分析报告

1. 概述

本报告是"实体-VO转换机制与缓存策略任务拆分"子任务1的执行结果旨在分析Contract-Manager项目中实体-VO转换机制和Service类结构为将Server模块Service缓存从实体对象调整为VO对象提供基础分析。

2. 核心接口体系分析

2.1 Voable接口

Voable<T>是实体类实现的核心接口用于将实体转换为VO对象

public interface Voable<T> {
    /**
     * 转换为Vo 
     * 
     * @return
     */
    T toVo();
}

该接口非常简洁,只定义了一个toVo()方法用于将实体对象转换为对应的VO对象。

2.2 QueryService接口

QueryService<Vo>是查询服务接口,提供通用的分页查询能力:

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的服务接口

public interface VoableService<M, Vo> {
    void updateByVo(M model, Vo vo);
}

该接口定义了一个updateByVo()方法用于根据VO对象更新对应的实体对象。

2.4 IEntityService接口

IEntityService<T>是实体服务接口提供基础的CRUD操作

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对象:

public class Contract
        implements IdentityEntity, NamedEntity, BasedEntity, CompanyBasedEntity, Serializable, Voable<ContractVo> {
    // 实体属性定义
    // ...
}

3.2 VO类结构

ContractVo是一个简单的POJO类使用@Data注解简化代码:

@Data
public class ContractVo implements IdentityEntity, NamedEntity, CompanyBasedVo, ProjectBasedVo {
    // VO属性定义
    // ...
}

3.3 转换实现

Contract类实现了toVo()方法用于将实体转换为VO

@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并实现多个接口:

@Service
@CacheConfig(cacheNames = "contract")
public class ContractService extends EntityService<Contract, Integer> implements QueryService<Contract>, VoableService<Contract, ContractVo> {
    // Service方法实现
    // ...
}

4.2 缓存配置

Service类使用@CacheConfig注解配置缓存名称:

@CacheConfig(cacheNames = "contract")

在Server模块中共有58个Service类使用了@CacheConfig注解配置缓存。

4.3 缓存使用

查询方法通常使用@Cacheable注解缓存结果:

@Cacheable(key = "#id")
public Contract findById(Integer id) {
    // 实现逻辑
}

增删改方法通常使用@Caching等注解清除缓存:

@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. 处理好关联实体的转换和缓存

本报告为后续的子任务提供了基础分析,帮助确定具体的实现方案和步骤。