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

如何用Lombok生成枚举的fromCode方法及AttributeConverter?

解决方案

一、生成fromCode方法的替代方案

Lombok本身没有内置注解可以直接生成枚举的fromCode反向查找方法,但完全不用在每个枚举里复制粘贴循环代码,以下是几种更优雅的实现方式:

1. 预初始化映射Map(高效简洁)

在枚举内部初始化一个code -> 枚举实例的Map,查找效率为O(1),代码量极少:

@AllArgsConstructor
@Getter
public enum FOO {
    ALICE("A"), BOB("B");

    private final String code;
    // 预初始化映射Map
    private static final Map<String, FOO> CODE_TO_ENUM = Arrays.stream(values())
            .collect(Collectors.toMap(FOO::getCode, Function.identity()));

    public static FOO fromCode(String code) {
        return CODE_TO_ENUM.get(code);
    }
}

注:用@Getter注解自动生成code字段的getter,或者手动编写,否则Lambda表达式无法访问私有字段

2. 通用工具类(复用逻辑)

写一个通用的枚举工具类,把查找逻辑抽离出来,所有枚举共享:

import java.util.function.Function;

public class EnumLookupUtils {
    /**
     * 根据指定字段反向查找枚举实例
     * @param enumClass 枚举类
     * @param targetValue 目标字段值
     * @param fieldExtractor 字段提取器(从枚举实例中获取要匹配的字段)
     * @return 匹配的枚举实例,无匹配返回null
     */
    public static <E extends Enum<E>, V> E lookupByField(Class<E> enumClass, V targetValue, Function<E, V> fieldExtractor) {
        for (E enumInstance : enumClass.getEnumConstants()) {
            V fieldValue = fieldExtractor.apply(enumInstance);
            if (targetValue == null ? fieldValue == null : targetValue.equals(fieldValue)) {
                return enumInstance;
            }
        }
        return null;
    }
}

然后在枚举中只需一行代码调用:

@AllArgsConstructor
@Getter
public enum FOO {
    ALICE("A"), BOB("B");

    private final String code;

    public static FOO fromCode(String code) {
        return EnumLookupUtils.lookupByField(FOO.class, code, FOO::getCode);
    }
}

二、生成JPA AttributeConverter的方案

同样不用手动编写完整的Converter类,通用方案如下:

1. 通用基类Converter

实现一个抽象的基类Converter,所有枚举的Converter只需继承并传入必要参数:

import jakarta.persistence.AttributeConverter;
import java.util.function.Function;

public abstract class BaseEnumConverter<E extends Enum<E>, C> implements AttributeConverter<E, C> {
    private final Class<E> enumClass;
    private final Function<E, C> toDbColumn;
    private final Function<C, E> toEntity;

    protected BaseEnumConverter(Class<E> enumClass, Function<E, C> toDbColumn, Function<C, E> toEntity) {
        this.enumClass = enumClass;
        this.toDbColumn = toDbColumn;
        this.toEntity = toEntity;
    }

    @Override
    public C convertToDatabaseColumn(E attribute) {
        return attribute == null ? null : toDbColumn.apply(attribute);
    }

    @Override
    public E convertToEntityAttribute(C dbData) {
        return dbData == null ? null : toEntity.apply(dbData);
    }
}

然后你的枚举对应的Converter只需写几行代码:

// 可放在枚举内部,也可单独作为类
public class FooConverter extends BaseEnumConverter<FOO, String> {
    public FooConverter() {
        super(FOO.class, FOO::getCode, FOO::fromCode);
    }
}

之后在实体类中直接使用:

@Entity
public class SomeEntity {
    @Convert(converter = FooConverter.class)
    private FOO foo;
    // 其他字段...
}

2. 自定义注解处理器(进阶方案)

如果想完全实现你说的@MagicEnumConverterAnnotation效果,可以自己编写注解处理器,在编译时自动生成Converter类。不过这个需要一定的注解处理器开发基础,适合需要大量枚举Converter的场景。


内容的提问来源于stack exchange,提问作者Loïc Gammaitoni

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 13:18:19