You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Mapstruct如何实现String类型code与多类枚举的双向互转

解决方案

第一步:定义通用枚举基接口

先给所有带Code属性的枚举抽取公共接口,统一获取Code的方法:

public interface BaseEnum<T> {
    T getCode();
}

所有需要按Code匹配的枚举都实现该接口,示例:

public enum TxAccTypeDto implements BaseEnum<String> {
    FINANCE("Finance");

    private final String code;
    TxAccTypeDto(String code) { this.code = code; }
    @Override
    public String getCode() { return code; }
}

public enum TxStatusDto implements BaseEnum<String> {
    PENDING("Pending");

    private final String code;
    TxStatusDto(String code) { this.code = code; }
    @Override
    public String getCode() { return code; }
}

第二步:实现通用枚举转换工具

封装通用的Code转枚举逻辑,支持任意实现了BaseEnum的枚举类型:

public class EnumConverterUtil {
    public static <E extends Enum<E> & BaseEnum<String>> E codeToEnum(String code, Class<E> enumClass) {
        if (code == null || enumClass == null) {
            return null;
        }
        for (E enumConstant : enumClass.getEnumConstants()) {
            if (code.equals(enumConstant.getCode())) {
                return enumConstant;
            }
        }
        // 匹配不到可根据业务需求返回null或抛异常
        return null;
    }
}

第三步:定义通用Mapstruct转换父接口

借助Mapstruct提供的@TargetType注解自动获取目标枚举类型,无需手动指定:

import org.mapstruct.TargetType;

public interface BaseEnumMapper {
    // String转枚举:自动识别目标枚举类型,兼容带Code的枚举和普通枚举
    default <E extends Enum<E>> E stringToEnum(String code, @TargetType Class<E> enumClass) {
        if (code == null) {
            return null;
        }
        // 优先匹配带Code的BaseEnum实现类枚举
        if (BaseEnum.class.isAssignableFrom(enumClass)) {
            return EnumConverterUtil.codeToEnum(code, (Class<E & BaseEnum<String>>) enumClass);
        }
        // 普通枚举按枚举名称匹配(比如示例中的ContactMethod)
        try {
            return Enum.valueOf(enumClass, code);
        } catch (IllegalArgumentException e) {
            return null;
        }
    }

    // 可选:枚举反向转String,DTO转Entity时用
    default <E extends Enum<E>> String enumToString(E enumValue) {
        if (enumValue == null) {
            return null;
        }
        if (enumValue instanceof BaseEnum<?>) {
            return (String) ((BaseEnum<?>) enumValue).getCode();
        }
        return enumValue.name();
    }
}

第四步:业务Mapper直接继承使用

你的业务Mapper仅需继承BaseEnumMapper,无需额外配置单个字段的映射规则:

import org.mapstruct.Mapper;

// 若使用Spring容器管理则加componentModel = "spring",否则去掉即可
@Mapper(componentModel = "spring")
public interface TxMapper extends BaseEnumMapper {
    TxEntity toEntity(TxDto dto);
    TxDto toDto(TxEntity entity);
}

效果验证

完全满足你的两个需求:

  • 业务代码仅需调用toEntity/toDto方法即可完成自动转换,无需传入额外参数
  • 新增枚举类型时,带Code的枚举仅需实现BaseEnum<String>接口,普通枚举无需任何改造,不用新增转换逻辑也不用修改Mapper配置

内容的提问来源于stack exchange,提问作者DSEyers

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 06:06:04