处理更改的ENUM定义 - 数据库

时间:2017-10-02 09:38:14

标签: java spring oracle enums

简介

首席架构师在春季启动项目中改变了ENUM定义。

自:

public enum ProcessState{
    C("COMPLETE"), P("PARTIAL");
}

要:

public enum ProcessState{
    COMPLETE("COMPLETE"), PARTIAL("PARTIAL");
}

处理这个问题的正确方法是什么?其他一些Java Spring Boot应用程序现在正在破坏。有没有办法告诉杰克逊解串器在这些情况下进行某种转换?

我当前的解决方案

我所做的是在oracle数据库上运行两个更新语句:

UPDATE store set PAYLOAD =  REPLACE(PAYLOAD, '"processState":"P"','"processState":"PARTIAL"') where PAYLOAD like '%"processState":"P"%';

UPDATE store set PAYLOAD =  REPLACE(PAYLOAD, '"processState":"C"','"processState":"COMPLETE"') where PAYLOAD like '%"processState":"C"%';

问题

还有其他方法吗?我可以通过在某些特定情况下添加一些反序列化/转换代码来实现吗?有没有比运行替换SQL语句更优雅的方法?

我可以对特定的java子包进行某种破解,然后说"使用这个枚举而不是枚举..."或者使用两者中的一个?但是不影响其余的代码?

错误:

java.lang.IllegalArgumentException: No enum constant 

3 个答案:

答案 0 :(得分:1)

理想情况下,我们存储的是emum而不是Enum的价值 因此,您应该保存ENUM值,例如COMPLETE,PARTIAL
对于JSON序列化和反序列化,请使用@JsonValue

sbt scalaVersion

答案 1 :(得分:1)

实现这样的JPA转换器:

@Converter(autoApply = true)
public class ProcessStateConverter
        implements AttributeConverter<ProcessState, String> {


    private ImmutableBiMap<ProcessState, String> map = ImmutableBiMap.<ProcessState, String>builder()
            .put(COMPLETE, "C")
            .put(COMPRESSING, "P")
        .build();

    @Override
    public String convertToDatabaseColumn(ProcessState attribute) {
        return Optional.ofNullable(map.get(attribute))
                .orElseThrow(() -> new RuntimeException("Unknown ProcessState: " + attribute));
    }

    @Override
    public ProcessState convertToEntityAttribute(String dbData) {
        return Optional.ofNullable(map.inverse().get(dbData))
                .orElseThrow(() -> new RuntimeException("Unknown String: " + dbData));
    }
}

请记住将您的Enum视为一个简单的列,而不是@Enumerated

@Entity
public class MyEntity {

    @Column //no @Enumerated
    private ProcessState processState; 

    //...
}

缺点是每次发生变化时都需要维护转换器。因此,最好创建一个单元测试来检查是否所有内容都已正确映射。

答案 2 :(得分:1)

其他人的另一个解决方案是:

   @JsonCreator
        public static ProcessState factory(String inputValue) {

        if(inputValue.length() == 1){

            for(ProcessState type : ProcessState.values()){
                if(inputValue.equals(type.getValue().substring(0,inputValue.length()))){
                    return type;
                }
            }
        }


        return ProcessState .valueOf(inputValue);
}