2011-06-16 63 views
2

我在我的应用程序(从域对象DTO,和反向),类似于下面的例子深物业映射:与自定义转换器推土机深属性格式映射

... 

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

... 

当推土机转换域名到DTO,它将employee.id映射到employeeId,那没关系。
当Dozer将DTO转换为域时,它将employeeId映射到id = employeeId的新Employee实例。

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

编辑: 更确切地说,我需要的是在域图employeenull如果employeeId在DTO是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在Domain对象仅仅是名称ID场。用这个名字,我只是在我的转换器中调用setter或getter方法。可能它不是最快乐的解决方案,但它适用于我的问题场景。

+0

对于DTO->域的情况下,你想与ID这已经是持续在数据库中执行员工的查找? – 2011-06-16 03:13:41

+0

@Terrell Plotzki - 不完全。如果DTO.employeeId为0或更少,我只想将Domain.employee设置为null。我改变了我的问题。 – slomir 2011-06-16 09:40:17

回答

0

你想要一个CustomConverter映射的父对象,例如:

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

DTO

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

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

你想使用CustomConverter两类PersonAPersonB地图,这会让你构建他们想要的任何方式。

1

您可以使用CustomConverter(根据对方的回答)一个,或使用DozerEventListener设置员工对象回空映射完成后,如果ID为0

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.employeePersonDTO.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将被设置为空。

退房的ModelMapper网站更多的文档和示例:

http://modelmapper.org

+0

您必须在答案中公布您与产品的关系。 – Brandon 2014-11-19 15:46:13

+0

没问题 - 完成 – Jonathan 2014-11-19 18:45:23