2017-01-16 70 views
1

的列表,請考慮以下情況:Orika:地圖從字符串到SomeObjects

public class A { 
    private String stringA; 

    public String getStringA() { 
     return stringA; 
    } 

    public void setStringA(String stringA) { 
     this.stringA = stringA; 
    } 

} 

public class B { 

    List<SomeObject> someObjects; 

    public List<SomeObject> getSomeObjects() { 
     if (someObjects == null) { 
      someObjects = new ArrayList<SomeObject>(); 
     } 
     return someObjects; 
    } 

} 

public class SomeObject { 
    private String stringSomeObject; 

    public String getStringSomeObject() { 
     return stringSomeObject; 
    } 

    public void setStringSomeObject(String stringSomeObject) { 
     this.stringSomeObject = stringSomeObject; 
    } 

} 

我要地圖從AB。在映射這些時,stringA需要映射到stringSomeObjectSomeObject。我試着寫了這樣的Orika映射器:

public class MyMapper extends ConfigurableMapper { 

    @Override 
    protected void configure(MapperFactory factory) { 
     ConverterFactory converterFactory = factory.getConverterFactory(); 
     converterFactory.registerConverter(new StringToSomeObjectConverter()); 

     factory.classMap(A.class, B.class) // 
       .field("stringA", "someObjects") // 
       .byDefault() // 
       .register(); 
    } 

} 

它映射類AB,每當遇到從String轉換到List<SomeObject>它調用自定義轉換器:

public class StringToSomeObjectConverter extends CustomConverter<String, List<SomeObject>> { 

    private static final String BORROWER_PARTY_TYP_CODE = "147"; 

    @Override 
    public List<SomeObject> convert(String source, Type<? extends List<SomeObject>> destinationType) { 
     SomeObject someObject = new SomeObject(); 
     someObject.setStringSomeObject(source); 
     return Arrays.asList(someObject); 
    } 

} 

我寫的一個單元測試,以確保其工作原理:

@Test 
public void testMap() throws Exception { 
    A a = new A(); 
    a.setStringA("a"); 

    B outcome = new MyMapper().map(a, B.class); 

    assertThat(outcome.getSomeObjects.size(), is(1)); 
} 

遺憾的是本次測試失敗:

java.lang.AssertionError: 
Expected: is <1> 
    but: was <0> 

這似乎是從來沒有執行轉換器,所以我試圖調試它。事實上:調試器永遠不會到達轉換器。難道我做錯了什麼?這好像是。我知道還有更多的方法可以用,比如:mapAToB例如...

好吧,我發現了一個solut ... nah!這不是一個解決方案,它只是一個解決方法。我也將stringA定義爲List<String>,並定義了一個擴展CustomConverter<String, LoanContrReqERPCrteReqLoanContrBrrwrPty>的轉換器。

因爲這感覺有點「哈克」,我仍然對一個很好的解決方案感興趣。 (雖然我只是認爲這個解決方案可能沒問題:現在兩個對象的數據結構比以前更加平等,問題是,該對象B來自外部服務,我無法修改它。)

回答

2

您映射不起作用,因爲您沒有設置someObjects

當Orika嘗試以產生用於映射器代碼時,它檢查在classMap所有fieldMapssourceProperty是可讀且destinationProperty是可分配的。如果檢查通過,生成器會將字段轉換放入生成的映射器中。如果檢查失敗,Orika只需跳過此字段轉換。

幾個選項,你可以用它來解決問題:

  • 您可以someObjectsB類中添加二傳:

    public static class B { 
    
        List<SomeObject> someObjects; 
    
        public List<SomeObject> getSomeObjects() { 
         if (someObjects == null) { 
          someObjects = new ArrayList<SomeObject>(); 
         } 
         return someObjects; 
        } 
    
        public void setSomeObjects(List<SomeObject> someObjects) { 
         this.someObjects = someObjects; 
        } 
    } 
    
  • 使用自定義映射器,而不是轉換器:

Orika在解析字段映射後將調用customMapper。
生成映射器會看起來像:

b.setOtherField(a.getOtherField()); 
    if (customMapper != null) { 
     customMapper.map(source, destination); <-- Your mapper invocation 
    } 
  • 使用遵循語法字段:

    factory.classMap(A.class, B.class) 
          .field("stringA", "someObjects[0].stringSomeObject") 
          .byDefault() 
          .register(); 
    

生成映射器會看起來像:

if (source.getStringA() != null) { 
     if (((((java.util.List) destination.getSomeObjects()).size() <= 0 || ((List) destination.getSomeObjects()).get(0) == null))) { 
      ((java.util.List) destination.getSomeObjects()).add(0, ((BoundMapperFacade) usedMapperFacades[0]).newObject(((String) source.getStringA()), mappingContext)); 
     } 
    } 

    if (!(((java.lang.String) source.getStringA()) == null)) { 
     (((java.util.List) destination.getSomeObjects()).get(0)).setStringSomeObject(source.getStringA()); 
    } else if (!(((java.util.List) destination.getSomeObjects()) == null) && !((((java.util.List) destination.getSomeObjects()).size() <= 0 || ((List) destination.getSomeObjects()).get(0) == null))) { 
     (((java.util.List) destination.getSomeObjects()).get(0)).setStringSomeObject(null); 
    } 

也有一個錯誤我n Orika使用語法.field("stringA", "elements{stringB}")Incorrect mapper code generated for mapping from a single property to property of collection element)從單個屬性映射到集合的屬性。 Bug在2016年12月31日關閉:Fix for bug

+0

請閱讀我的「編輯」 - 部分。我不能修改B類。 – Chris311

+0

好吧,還有一個問題:使用.customize()與自定義映射器並使用Converter之間有什麼區別? – Chris311

+0

如果目標屬性是可分配的(換句話說,如果你有這個字段的設置器),字段的自定義轉換器將被放入生成的映射器中。對於自定義映射器生成的代碼將如下所示: ' b.setField1(a.getField1()); if(customMapper!= null){ customMapper.map(a,b) } ' –

相關問題