Java中枚举的通用接口

时间:2017-07-16 14:53:05

标签: java generics enums

我在Hibernate / Spring上有一个Web应用程序,我想在应用程序中使用的枚举很少

public enum MerchantStatus {
    NEW("New"),
    ...

    private final String status;

    MerchantStatus(String status) {
        this.status = status;
    }

    public static MerchantStatus fromString(String status) {..}    

    public String toString() {..}
}

public enum EmployerType {
    COOL("Cool"),
    ...

    private final String type;

    EmployerType (String type) {
        this.type = type;
    }

    public static EmployerType fromString(String type) {..}    

    public String toString() {..}
}

我想创建转换器以将我的枚举对象转换为字符串,反之亦然。它是这样的:

public class MerchantStatusConverter implements AttributeConverter<MerchantStatus, String> {
    public String convertToDatabaseColumn(MerchantStatus value) {..}

    public MerchantStatus convertToEntityAttribute(String value) {..}
}

问题是我不想为每个枚举创建转换器,理想情况下它应该是泛型类/接口,我将在这里使用多态。问题是fromString是静态方法,似乎无法创建返回泛型类型的静态方法。

这个问题有什么解决方案吗?

3 个答案:

答案 0 :(得分:2)

  

问题是我不想为每个枚举创建转换器   理想情况下,它应该是通用类/接口,我将使用   多态性在这里。

您无法选择,因为在注释您的实体时无法参数化AttributeConverter实施。

您确实应该只使用AttributeConverter类指定它:

@Enumerated(EnumType.STRING)
@Convert(converter = MerchantStatusConverter.class)
private MerchantStatus merchantStatus;

但是你可以定义一个抽象类来定义逻辑并在每个枚举类中对其进行子类化 要实现它,您应该在每个枚举类前面引入一个声明fromString()toString()方法的接口。

界面:

public interface MyEnum<T extends MyEnum<T>>{

     T fromString(String type);
     String toString(T enumValue);
}

实现接口的枚举:

public enum MerchantStatus implements MyEnum<MerchantStatus> {

    NEW("New"), ...


    @Override
    public MerchantStatus fromString(String type) {
     ...
    }

    @Override
    public String toString(MerchantStatus enumValue) {
     ...
    }
}

摘要AttributeConverter类:

public abstract class AbstractAttributeConverter<E extends MyEnum<E>> implements AttributeConverter<E, String> {

    protected MyEnum<E> myEnum;

    @Override
    public String convertToDatabaseColumn(E attribute) {
        return myEnum.toString(attribute);
    }

    @Override
    public E convertToEntityAttribute(String dbData) {
        return myEnum.fromString(dbData);
    }
}

具体AttributeConverter类需要声明一个公共构造函数,以将受保护的myEnum字段分配给枚举值(无论如何):

public class MerchantStatusAttributeConverter extends AbstractAttributeConverter<MerchantStatus> {
   public MerchantStatusAttributeConverter(){
      myEnum = MerchantStatus.NEW; 
   }
}

答案 1 :(得分:1)

您应该能够执行以下操作:

    INSERT INTO search_by_date(date,total_count)
      VALUES( '02-05-2017'::DATE , 50 )
       ON CONFLICT(date,total_count)  
    DO UPDATE SET date = EXCLUDED.date, total_count = EXCLUDED.total_count;

答案 2 :(得分:1)

如果您想为所有enum课程使用常规转换器,只要遵守命名约定,就可以使用反射。

您的惯例似乎是toString()用于enum - &gt;转化为StringstaticfromString(String) String - &gt; enum转化。

转换器就是这样的:

public class EnumConverter<T extends Enum<T>> implements AttributeConverter<T, String> {
    private final Method fromStringMethod;

    public EnumConverter(Class<T> enumClass) {
        try {
            this.fromStringMethod = enumClass.getDeclaredMethod("fromString", String.class);
        } catch (NoSuchMethodException e) {
            throw new NoSuchMethodError(e.getMessage());
        }
        if (! Modifier.isStatic(this.fromStringMethod.getModifiers()))
            throw new NoSuchMethodError("fromString(String) is not static");
        if (this.fromStringMethod.getReturnType() != enumClass)
            throw new NoSuchMethodError("fromString(String) does not return " + enumClass.getName());
    }

    public String convertToDatabaseColumn(T value) {
        return value.toString();
    }

    @SuppressWarnings("unchecked")
    public T convertToEntityAttribute(String value) {
        try {
            return (T) this.fromStringMethod.invoke(null, value);
        } catch (IllegalAccessException e) {
            throw new IllegalAccessError(e.getMessage());
        } catch (InvocationTargetException e) {
            throw new RuntimeException("Error calling fromString(String): " + e, e);
        }
    }
}

然后通过命名类来构造它,例如

new EnumConverter<>(MerchantStatus.class)
new EnumConverter<>(EmployerType.class)