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;
}
}
我很苦恼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;
}
}