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代码中,我会像这样执行转换

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

默认情况下,Dozer 不执行此转换,因为Target没有foos属性(只是一个 getter)。

实际上,我有很多这样的属性需要映射。一种选择是告诉 Dozer直接映射私有字段,但这并不完全令人满意,因为:

  • 我将需要在 Dozer XML 配置中按名称指定要以这种方式映射的每个字段
  • 访问私有字段是不好的

有没有更好的办法?

4

4 回答 4

1

is-accessible除了标志之外,没有简单的方法可以解决这个问题。但是您可以定义一个使用 getter 的自定义转换器来执行以下操作:

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

这将是非常繁重的工作和大量的工作。您需要在两者之间定义一个自定义转换器(参见http://dozer.sourceforge.net/documentation/customconverter.htmlSource并且Target使用 getter 而不是 setter:

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

我想,祝你好运

于 2011-04-21T14:09:51.107 回答
1

您可以查看ModelMapper作为 Dozer 的替代品。处理这种情况很简单:

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

这为所有私有字段启用了字段匹配。要执行映射:

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

查看 ModelMapper 网站了解更多信息:

http://modelmapper.org

于 2011-06-24T04:44:59.800 回答
1

您可以向 Target 添加一个方法:

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>

也许建议一个允许在 setter 或 getter 表达式中使用 EL 的功能

于 2011-05-29T20:56:30.383 回答
0

例如,如果您没有列表值的设置器(就像我出于某种原因...),您可以将字段映射与“this”结合使用,以识别您可以使用“key”的属性:

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

然后,您可以继续实施转换器。您将获得包含字段“variablename”作为源的对象。您现在可以按照您需要的方式操作源对象(在这种情况下,使用 getter、获取列表、addAll() 就可以了)。

于 2017-11-21T16:16:35.823 回答