Files
contract-manager/docs/task/string_converter_implementation_guide.md
songqq 09b0da498b feat(service): 实现国际化支持并优化Service层
重构文件类型相关Service以支持国际化查询
添加findOneByLang辅助方法统一查询逻辑
实现StringConverter支持UI控件显示
优化缓存配置和查询性能
新增UnitStringConverter和CustomerCatalogStringConverter
完善文档和测试用例
2025-09-24 16:20:49 +08:00

3.9 KiB
Raw Blame History

StringConverter 创建规则与实现逻辑

目的

StringConverter 在 Contract-Manager 项目中用于:

  • 在UI组件如ComboBox中显示对象的可读字符串表示
  • 从用户输入的字符串中还原对应的对象实例
  • 支持表单数据的绑定和转换

创建规则

1. 文件位置

StringConverter 类应位于 com.ecep.contract.converter 包下

2. 命名规范

  • 类名格式:[EntityName]StringConverter
  • 例如:CustomerCatalogStringConverterVendorCatalogStringConverter

3. 继承关系

  • 实现 javafx.util.StringConverter<T> 接口其中T为实体的VO类型
  • 例如:StringConverter<CustomerCatalogVo>

4. 构造函数

  • 通常需要注入对应的Service实例
  • 构造函数接收Service作为参数
  • 例如:public CustomerCatalogStringConverter(CustomerCatalogService service)

5. 核心方法实现

toString(T object)

  • 将对象转换为可读的字符串表示
  • 通常返回对象的名称或关键标识
  • 处理null情况

fromString(String string)

  • 从字符串还原对象实例
  • 通常调用Service的findByName或findByCode方法

与Service类的关联

1. 在Service类中创建Converter实例

@Service
@CacheConfig(cacheNames = "[entity-name]-cache")
public class [EntityName]Service extends QueryService<[EntityName]Vo, [EntityName]ViewModel> {
    
    private final [EntityName]StringConverter stringConverter = new [EntityName]StringConverter(this);
    
    // 实现findByName方法供StringConverter使用
    public [EntityName]Vo findByName(String name) {
        return findAll(ParamUtils.builder().equals("name", name).build(), Pageable.ofSize(1))
               .stream().findFirst().orElse(null);
    }
    
    @Override
    public StringConverter<[EntityName]Vo> getStringConverter() {
        return stringConverter;
    }
}

2. 缓存配置

Service类通常需要添加缓存注解以提高性能

  • @Cacheable(key = "#id") 用于findById方法
  • @Cacheable(key = "'all'") 用于findAll方法
  • @Caching(evict = {@CacheEvict(key = "'all'"), @CacheEvict(key = "#entity.id")}) 用于save和delete方法

示例实现

CustomerCatalogStringConverter 示例

package com.ecep.contract.converter;

import com.ecep.contract.service.CustomerCatalogService;
import com.ecep.contract.vo.CustomerCatalogVo;
import javafx.util.StringConverter;

public class CustomerCatalogStringConverter extends StringConverter<CustomerCatalogVo> {
    private final CustomerCatalogService service;

    public CustomerCatalogStringConverter(CustomerCatalogService service) {
        this.service = service;
    }

    @Override
    public String toString(CustomerCatalogVo object) {
        return object == null ? "" : object.getName();
    }

    @Override
    public CustomerCatalogVo fromString(String string) {
        return service.findByName(string);
    }
}

使用场景

在UI组件中的使用

StringConverter 主要用于:

  • ComboBox的数据绑定和显示
  • 表单字段的字符串转换
  • 表格单元格的格式化显示

获取StringConverter实例

// 方式1直接从Service获取
StringConverter<CustomerCatalogVo> converter = customerCatalogService.getStringConverter();

// 方式2通过Spring容器获取
StringConverter<CustomerCatalogVo> converter = context.getBean(CustomerCatalogStringConverter.class);

常见模式

  1. 基础模式直接继承StringConverter实现toString和fromString方法
  2. 组件模式继承EntityStringConverter基类设置初始化、建议和字符串转换方法
  3. 枚举模式:针对枚举类型的特殊处理

注意事项

  1. 确保Service类实现了必要的find方法如findByName
  2. 处理null值情况避免空指针异常
  3. 考虑缓存策略,提高频繁转换场景下的性能
  4. 保持Converter与Service的同步更新确保字段变更时转换逻辑也相应更新