2017-06-06 237 views
1

這裏是我的源對象:MapStruct:與HashMap中的條目處理源

public class Record { 

    public final long captureTime; 
    public final String environnement; 
    public final String bundle; 
    public final String type; 
    public final String id; 
    public final Map<String,Object> meta; 

} 

這是我的目標對象:

public class MappedRecord { 

    public final long captureTime; 
    public final String environnement; 
    public final String bundle; 
    public final String type; 
    public final String id; 
    public final String ip; 
    public final String server; 

} 

我的映射如下所示:

public interface RecordMapper { 

    RecordMapper MAPPER = Mappers.getMapper(RecordMapper.class); 


    @Mappings({ 
     @Mapping(source = "captureTime", target = "captureTime"), 
     @Mapping(source = "environnement", target = "environnement"), 
     @Mapping(source = "bundle", target = "bundle"), 
     @Mapping(source = "type", target = "type"), 
     @Mapping(source = "id", target = "id"), 
     @Mapping(expression = "java((String) r.meta.get(\"ip\"))", target = "ip"), 
     @Mapping(expression = "java((String) r.meta.get(\"server\"))", target = "server"), 
    }) 

    MappedRecord toMappedRecord(Record r); 

} 

現在它運行良好,但我想知道是否有一個更「優雅」的方式來設置地圖項作爲源。因爲有了這個,我沒有設法使用「qualifiedByName」屬性添加轉換函數,它看起來只能在指定「源」時才能工作。我誤解了什麼?

我嘗試沒有滿意的結果以下方法:

  • 覆蓋getter方法中的特定字段我Record類
  • 添加一個轉換功能與「qualifiedByName」屬性。例如:

    @Named("metaGetter") 
    default String dataGetter (String property) { 
        return (String) r.meta.get(property); 
    } 
    

    但顯然這不會編譯,因爲屬性名稱無效作爲適當的來源。

謝謝你的時間。

回答

1

自己寫的預選賽:

public class MappingUtil { 
    @Qualifier 
    @Target(ElementType.METHOD) 
    @Retention(RetentionPolicy.SOURCE) 
    public @interface Ip { 
    } 
    @Qualifier 
    @Target(ElementType.METHOD) 
    @Retention(RetentionPolicy.SOURCE) 
    public static @interface Server { 
    } 
    @Ip 
    public String ip(Map<String, Object> in) { 

     return (String)in.get("ip"); 
    } 
    @Server 
    public String server(Map<String, Object> in) { 

     return (String)in.get("server"); 
    } 
} 

,然後只需添加到映射:

@Mapper(uses = MappingUtil.class) 
public interface SourceTargetMapper { 

    SourceTargetMapper MAPPER = Mappers.getMapper(SourceTargetMapper.class); 

    @Mappings({ 
     @Mapping(source = "map", target = "ip", qualifiedBy = MappingUtil.Ip.class), 
     @Mapping(source = "map", target = "server", qualifiedBy = MappingUtil.Server.class), 
    }) 
    Target toTarget(Source s); 
} 
+0

謝謝您的回答。它確實可以幫助。但是我不喜歡這個屬性在MappingUtil類中被硬編碼的事實:/這是否真的是您認爲的唯一方式? – nbchn

+0

@nbchn沒有硬編碼值的映射是沒有辦法的。 MapStruct在這裏非常安全,就像字段名稱改變一樣,它會引發編譯錯誤。在發佈之前,我已經測試過該解決方案,並且它正常工作。 – xenteros

+0

嗯,我想我沒有選擇。感謝您的寶貴幫助。我使用@Named註釋做了一些更緊湊的映射器上的所有事情:)我嘗試級聯轉換函數(像Map map - [server] - > String server - [toLowerCase] - >字符串lowerCasedServer),但沒有設法使其工作,似乎只有第一個應用。我不得不把所有的轉換都放在一個函數中。任何線索? – nbchn