# StringConverter 创建规则与实现逻辑

## 目的
StringConverter 在 Contract-Manager 项目中用于：
- 在UI组件（如ComboBox）中显示对象的可读字符串表示
- 从用户输入的字符串中还原对应的对象实例
- 支持表单数据的绑定和转换

## 创建规则

### 1. 文件位置
StringConverter 类应位于 `com.ecep.contract.converter` 包下

### 2. 命名规范
- 类名格式：`[EntityName]StringConverter`
- 例如：`CustomerCatalogStringConverter`、`VendorCatalogStringConverter`

### 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实例
```java
@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 示例
```java
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实例
```java
// 方式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的同步更新，确保字段变更时转换逻辑也相应更新