2011-04-21 96 views
1

我試圖用推土機來的定製推土機映射

class Source { 
    private List<Foo> foos = new ArrayList<Foo>(); 

    public List<Foo> getFoos() { 
    return foos; 
    } 

    public void setFoos(List<Foo> foos) { 
    this.foos = foos; 
    } 
} 

一個實例轉換的實例:

class Target { 
    private List<Foo> foos = new ArrayList<Foo>(); 

    public List<Foo> getFoos() { 
    return foos; 
    } 
} 

在Java代碼中,我將瓶坯converstion這樣

Source s = new Source(); 
Target t = new Target(); 
t.getFoos().addAll(s.getFoos()); 

推土機默認不執行此轉換,因爲Target沒有foos原型rty(只是一個getter)。

在現實中,我有很多像這樣的屬性,我需要映射。一種方法是,告訴推土機到map the private fields directly,但這並不完全令人滿意,因爲:

  • 我需要指定每個字段被這樣的名字在推土機XML配置映射
  • 訪問私有字段是不好

有沒有更好的方法?

+0

你意識到't.getFoos()。addAll(s.getFoos());'會導致上面的'Target'實現的NPE,是不是? – Thomas 2011-04-21 14:05:54

+0

對不起,我在「示例」代碼中犯了一個錯誤。我現在修復了它 – 2011-04-21 14:11:48

回答

1

有沒有簡單的方法來解決這個比is-accessible標誌。 但是你可以定義使用吸氣做一個自定義轉換器:

t.getFoos().addAll(s.getFoos()); 

這將是非常沉重的手和工作很多。您將需要SourceTarget所用的吸氣劑,而不是制定者之間定義自定義轉換器(見​​):

public class TestCustomConverter implements CustomConverter { 

    public Object convert(Object destination, Object source, Class destClass, Class sourceClass) { 
    if (source == null) { 
     return null; 
    } 
    if (source instanceof Source) { 
     Target dest = null; 
     // check to see if the object already exists 
     if (destination == null) { 
     dest = new Target(); 
     } else { 
     dest = (Target) destination; 
     } 
     dest.getFoos().addAll(((Source)source).getFoos()); 
     return dest; 
    } else if (source instanceof Target) { 
     Source dest = null; 
     // check to see if the object already exists 
     if (destination == null) { 
     dest = new Source(); 
     } else { 
     dest = (Source) destination; 
     } 
     dest.setFoos(((Target)source).getFoos()); 
     return dest; 
    } else { 
     throw new MappingException("Converter TestCustomConverter used incorrectly. Arguments passed in were:" 
      + destination + " and " + source); 
    } 
    } 

我想,運氣好的話

+0

現在我已經修復了NPE,你能告訴我如何使用自定義轉換器來解決這個問題嗎? – 2011-04-21 14:13:18

+0

感謝您的幫助,但上述解決方案僅適用於將'Source.foos'映射到'Target.foos'。我需要一個解決方案,用於映射任何兩個List類型的屬性,其中目標類中只有一個getter。 – 2011-04-22 13:07:10

+0

@don這是真的,但是你不能籠統地映射這些列表,因爲他們需要知道父類以使用getter。這是我能想到的唯一解決方案。 – Tnem 2011-04-22 14:50:36

1

你可以添加一個方法到目標:

public void addFoo(Foo item) { 
    foos.add(item); 
} 

<mapping> 
    <class-a>Source</class-a> 
    <class-b>Target</class-b> 
    <field> 
    <a>foos</a> 
    <b set-method="addFoo" type="iterate">foos</b> 
    </field> 
</mapping> 

也許表明某個功能,以允許在調節器或吸氣表達使用EL的

1

您可能會檢查出ModelMapper作爲推土機的替代品。處理這種情況很簡單:

ModelMapper modelMapper = new ModelMapper(); 
modelMapper.getConfiguration() 
    .enableFieldMatching(true) 
    .setFieldAccessLevel(AccessLevel.PRIVATE); 

所有私人領域這使場匹配。執行映射:

Target target = modelMapper.map(source, Target.class); 

退房的ModelMapper網站獲取更多信息:

http://modelmapper.org

0

舉例來說,如果你沒有一個列表值二傳手(像我有什麼理由...)您可以結合「this」使用字段映射,以確定您可以使用「key」的屬性:

<field custom-converter="de.xyz.custom.MyConverter"> 
    <a key="variablename">this</a> 
    <b>targetvariablename</b> 
</field> 

然後,您可以繼續執行轉換器。您將獲得包含「variablename」字段的對象作爲源。你現在可以按照你需要的方式操縱源對象(在這種情況下,使用getter,獲取列表,addAll(),你很好)。