2011-04-21 82 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(),你很好)。