2016-11-24 2 views
1

Ich leide Frühling-Mybatis Polyporphism Problem. Hier ist das Detail: Ich habe eine Entity:Frühling Mybatis Polymorphismus

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

public class Filter { 
    private String type; 
} 

Wenn die Filter polymorph sind. Es gibt einige Unterklassen auf Filter, wie:

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

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

Wie Sie sehen können, jede Unterklasse anderes Schema außer type hat.

Und die MySQL-Tabelle segment wie:

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; 

So um filter (varchar) in MYSQL deserialisieren ich diesen FilterTypeHandler machen:

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; 
    } 
} 

und um polymorphe Deserialisierung zu machen jackson tun , Ändere ich die Filterklasse:

@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; 
} 

aber das Ergebnis ist, dass Jackson ObjectMapper nicht alle Nachrichten deserialisieren kann.

Also gibt es etwas falsch? Welchen richtigen Schritt sollte ich machen? Nützliche Links oder Dokumente sind hilfreich.

+0

EIN Auch beim Erstellen von e segmentEntity mit Controller 'SegmentController' wie create (@RequestBody SegmentEntity segmentEntity) ist die Deserialisierung ebenfalls schwer zu programmieren. –

Antwort

0

Ich habe mein Problem gelöst mit Jackson Custom Deserializer. Hier ist meine solusion:

Zuerst habe ich Refactoring meine Bohnen, wie:

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

und:

@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 
} 

und der FilterJsonDeserializer ist:

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; 
    } 

}