Spring Mybatis 多态性

Spring Mybatis Polymorphism

我很苦恼Spring-Mybatis多态性问题。这是详细信息: 我有一个 Entity:

public class SegmentEntity {
    private int id;
    private String name;
    private Filter filter;
    // getter and setter
}

public class Filter {
    private String type;
}

过滤器是多态的。 Filter上有一些sub-class,比如:

public class OneFilter extends Filter {
    private String field1;
    private int field2;
}

public class AnotherFilter extends Filter {
    private List<Integer> field3;
    private double field4;
}

如您所见,每个子 class 都有不同的架构,除了 type

而 MySQL table segment 喜欢:

CREATE TABLE `segment` {
    `id` int(11) NUL NULL AUTO_INCREMENT,
    `name` varchar(32) NOT NULL,
    `filter` varchar(1024) NOT NULL,
    PRIMARY KEY (`id`)
} ENGINE=InnoDB DEFAULT CHARSET=utf8;

所以为了在 MYSQL 中反序列化 filter(varchar) 我做了这个 FilterTypeHandler:

public class FilterTypeHandler implements TypeHandler<Filter> {
    @Override
    public Filter getResult(ResultSet rs, String columnName) throws SQLException {
        String json = rs.getString(columnName);
        Filter filter = null;
        try {
            filter = new ObjectMapper().readValue(json, Filter.class);
        } catch (IOException e) {}
        return filter;
    }
}

为了让 jackson 进行多态反序列化,我更改了过滤器 class:

@JsonIgnoreProperties(ignoreUnknown = true)
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
@JsonSubTypes({@JsonSubTypes.Type(value = OneFilter.class, name = "someTypeName"),
           @JsonSubTypes.Type(value = AnotherFilter.class, name = "anotherTypeName")})
public class Filter {
    private String type;
}

但结果是,jackson ObjectMapper 无法反序列化所有消息。

所以有什么问题吗?我应该做什么正确的步骤? 任何有用的链接或文档都有帮助。

我已经使用 jackson 自定义解串器解决了我的问题。 这是我的解决方案:

首先我重构了我的 beans,比如:

@JsonDeserialize(using = FilterJsonDeserializer.class)
public interface Filter {
}

和:

@JsonDeserialize(as = OneFilter.class)
public class OneFilter implements Filter, Serializable {
    private String type;
    private String field1;
    private int field2;
    @JsonCreator
    public OneFilter(@JsonProperty("type") String type, @JsonProperty("field1") String field1, @JsonProperty("field2") int field2) {
        // omit
    }
    // getter and setter
    // override toString
}

@JsonDeserialize(as = AnotherFilter.class)
public class AnotherFilter implements Filter, Serializable {
    private String type;
    private List<Integer> field3;
    private double field4;
    @JsonCreator
    public AnotherFilter(@JsonProperty("type") String type, @JsonProperty("field3") List<Integer> field3, @JsonProperty("field4") double field4) {
        // omit
    }
    // getter and setter
    // override toString
}

FilterJsonDeserializer 是:

public class FilterJsonDeserializer extends JsonDeserializer<Filter> {
    private static final String TYPE = "type";
    @Override
    public Filter deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        Filter result = null;
        ObjectMapper = mapper = (ObjectMapper) jp.getCodec();
        ObjectNode root = mapper.readTree(jp);
        if (root.has(TYPE)) {
            String filterType = root.get(TYPE).asText();
            switch (filterType) {
                case FILTER1:
                    result = mapper.readValue(root.toString(), OneFilter.class);
                    break;
                case FILTER2:
                    result = mapper.readValue(root.toString(), AnotherFilter.class);
                    break;
                default:
                    throw new IllegalArgumentException("Not supported filter type.");
            }
        }
        return result;
    }

}