2

我的应用程序中有深层属性映射(从域对象到 DTO,反之亦然),类似于下一个示例:

...

<field>
    <a>employee.id</a>
    <b>employeeId</a>
</field>

...

当 Dozer 将 Domain 转换为 DTO 时,它映射employee.idemployeeId,就可以了。
当 Dozer 将 DTO 转换为 Domain 时,它会映射employeeId到 id=employeeId 的新 Employee 实例。

我想为这个深层属性映射创建一些逻辑,但我就是想不出解决方案。我尝试实现CustomConverter(或扩展DozerConverter)但 Dozer 将 Integer 类型作为源和目标类传递给我(并期望 Integer 作为结果)。

编辑:更准确地说,我需要employee在 Domain 中映射到null如果employeeIdDTO 中为 0。

这可能吗?

有什么建议吗?

根据答案编辑:我解决了现场级自定义转换器的问题。而不是前面提到的映射,现在我有这样的东西......

...

<field custom-converter="ManyToOneIdMapper" custom-converter-param="id">
    <a>employee</a>
    <b>employeeId</b>
</field>

...

在 ManyToOneIdMapper 我有...

public class ManyToOneIdMapper implements ConfigurableCustomConverter{

//...
//parameter field declaration, setParameter and getParameter implementations etc.
//...

public Object convert(Object existingDestinationFieldValue, Object sourceFieldValue, 
        Class<?> destinationClass, Class<?> sourceClass) {
    try {

        if(sourceClass.equals(Integer.class)){
            Integer src=(Integer)sourceFieldValue;

            if(src==null || src==0)
                return null;

            String setterName=formatMethodName("set", getParameter());
            Method setterMethod=destinationClass.getMethod(setterName, Integer.class);
            Object instance=destinationClass.newInstance();

            setterMethod.invoke(instance, src);

            return instance;
        }else{    
            if(sourceFieldValue==null)
                return 0;

            String getterName=formatMethodName("get", getParameter());
            Method getterMethod=sourceClass.getMethod(getterName);
            Object instance=getterMethod.invoke(sourceFieldValue);

            return instance;
        }
    } catch (Exception e){}
    return null;
}

/**
 * @return - method name (most often setter or getter)  according to fieldName.
 * For example formatMethodName("get", "id") returns "getId"
 */
protected String formatMethodName(String methodPrefix, String fieldName){
    String trimmedFieldName=fieldName.trim();
    String firstLetter=String.valueOf(trimmedFieldName.charAt(0));
    String capitalizedFirstLetter=firstLetter.toUpperCase();
    String methodName=methodPrefix+""+capitalizedFirstLetter+""+fieldName.substring(1);

    return methodName;
}

custom-converter-param只是域对象中 id 字段的名称。使用该名称,我只需在转换器中调用 setter 或 getter 方法。可能,这不是最快乐的解决方案,但它适用于我的问题场景。

4

3 回答 3

1

您可以使用 a CustomConverter(根据另一个答案),或者DozerEventListener如果 ID 为 0,则在映射完成后使用 a 将员工对象设置回 null。

于 2011-06-16T13:02:23.043 回答
0

您想要CustomConverter映射父对象,例如:

领域

class PersonA {
    ...
    int employeeId;
    ...
}

DTO

class PersonB {
    ...
    Employee employee;
    ...
}

class Employee {
    ...
    int id;
    ...
}

您想映射这两个类PersonAPersonB使用 a CustomConverter,这将让您以您想要的任何方式构造它们。

于 2011-06-16T12:30:15.173 回答
0

您可以查看ModelMapper(作者在这里)。它将智能地映射您描述的场景,而无需任何配置或自定义转换器。考虑模型:

class Person {
  Employee employee;
}

class Employee {
  int id;
}

class PersonDTO {
  int employeeId;
}

映射很简单:

ModelMapper modelMapper = new ModelMapper();
PersonDTO personDTO = modelMapper.map(person, PersonDTO.class);

为了有条件地映射Person.employeewhenPersonDTO.employeeId不为零,我们只需创建一个条件并使用条件为 Person.employee 添加一个属性映射:

Condition<?, ?> empIdIsNotZero = new Condition<PersonDTO, Employee>() {
  public boolean applies(MappingContext<PersonDTO, Employee> context) {
    return context.getSource().getEmployeeId() != 0;
  }
};

modelMapper.addMappings(new PropertyMap<PersonDTO, Person>() {
  protected void configure() {
    when(empIdIsNotZero).map(source).setEmployee(null);
  }
});

empIdIsNotZero条件适用时,映射将照常进行。否则将跳过映射并将Person.employee其设置为 null。

查看 ModelMapper 站点以获取更多文档和示例:

http://modelmapper.org

于 2011-06-23T19:17:47.470 回答