简体   繁体   English

自定义推土机映射

[英]custom dozer mapping

I'm trying to use Dozer to convert an instance of 我正在尝试使用推土机转换的实例

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

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

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

to an instance of: 到以下实例:

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

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

In Java code I would preform the converstion like this 在Java代码中,我会像这样进行对话

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

Dozer doesn't perform this conversion by default because Target doesn't have a foos property (just a getter). 默认情况下,推土机不执行此转换,因为Target没有foos属性(只是一个吸气剂)。

In reality, I have lots of properties like this that I need to map. 实际上,我有很多需要映射的属性。 One option is to tell Dozer to map the private fields directly , but this is not entirely satisfactory because: 一种选择是告诉Dozer 直接映射私有字段 ,但这并不完全令人满意,因为:

  • I will need to specify each field to be mapped in this way by name in the Dozer XML config 我需要在Dozer XML配置中通过名称指定要以此方式映射的每个字段
  • accessing private fields is bad 访问私有字段是不好的

Is there a better way? 有没有更好的办法?

There is no easy way to get around this other than the is-accessible flag. 除了is-accessible标志之外,没有其他简单的方法可以解决此问题。 But you could define a custom converter that uses the getter to do: 但是您可以定义一个使用getter的自定义转换器:

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

This would be very heavy handed and alot of work. 这将是非常繁重的工作和大量工作。 You would need to define a custom converter (see http://dozer.sourceforge.net/documentation/customconverter.html ) between Source and Target that used the getter instead of the setter: 您将需要在SourceTarget之间定义一个使用getter而不是setter的自定义转换器(请参阅http://dozer.sourceforge.net/documentation/customconverter.html ):

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

I think, good luck 我想,祝你好运

You could add a method to Target: 您可以向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>

Maybe suggest a feature to allow use of EL in a setter or getter expression 也许建议使用允许在setter或getter表达式中使用EL的功能

You might check out ModelMapper as an alternative to Dozer. 您可以签出ModelMapper替代Dozer。 Handling this scenario is trivial: 处理这种情况很简单:

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

This enabled field matching for all private fields. 这将为所有私有字段启用字段匹配。 To perform the mapping: 要执行映射:

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

Check out the ModelMapper site for more info: 请访问ModelMapper网站以获取更多信息:

http://modelmapper.org http://modelmapper.org

If for example you do not have a setter for a list value (like I had for whatever reason...) you can use the field mapping in combination with "this", to identify the attribute you can use "key": 例如,如果您没有列表值的设置器(例如由于某种原因我没有...),则可以将字段映射与“ this”结合使用,以标识可以使用“ key”的属性:

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

You can then proceed to implement the converter. 然后,您可以继续实施转换器。 You will be given the Object containing the field "variablename" as source. 将为您提供包含字段“变量名称”的对象作为源。 you are now able to manipulate the source object the way you need to (in this case use the getter, get the list, addAll() and you're good). 现在,您可以按照需要的方式操作源对象(在这种情况下,使用getter,获取列表,addAll()即可)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM