2016-02-02 33 views
0

通過this answer啓發映射不變對象的集合,我已經寫了一個定製conveter(你可以找到在Github repo整個工作示例)。對於推土機轉換之間:如何推土機

public class MyEntity { 
    private List<ObjectId> attachmentIds; 

    public List<ObjectId> getAttachmentIds() { return attachmentIds; } 

    public void setAttachmentIds(List<ObjectId> attachmentIds) { 
     this.attachmentIds = attachmentIds; 
    } 
} 

而其DTO:

public class MyEntityDto { 
    private List<FileDataDto> attachments; 

    public List<FileDataDto> getAttachments() { return attachments; } 

    public void setAttachments(List<FileDataDto> attachments) { 
     this.attachments = attachments; 
    } 
} 

MyEntity只保存存儲在蒙戈DATABSE文件的ID。它的DTO被髮送到JSON的前端,應該包含id和文件的文件名(這是FileDataDto類的內容)。我的轉換器:

public class FileIdToFileDataConverter extends DozerConverter<ObjectId, FileDataDto> { 
    public FileIdToFileDataConverter() {super(ObjectId.class, FileDataDto.class); } 

    @Override 
    public FileDataDto convertTo(ObjectId source, FileDataDto destination) { 
     if (source == null) { 
      return null; 
     } 
     FileDataDto fileData = destination == null ? new FileDataDto() : destination; 
     fileData.setId(source.toString()); 
     // fetch the file from repository and update the name from db 
     fileData.setFilename("myfile.txt"); 
     return fileData; 
    } 

    @Override 
    public ObjectId convertFrom(FileDataDto source, ObjectId destination) { 
     return source == null ? null : new ObjectId(source.getId()); 
    } 
} 

改建工程預期在MyEntity - >MyEntityDto方向。然而,它卻在相反的情況下失敗。它使用Dozer創建的ObjectId(作爲destination參數傳遞)而不是轉換器返回的那個。這個測試

@Test 
public void dtoToMyEntity() { 
    MyEntityDto dto = new MyEntityDto(); 
    FileDataDto fileData = new FileDataDto(); 
    fileData.setFilename("file.txt"); 
    fileData.setId(new ObjectId().toString()); 
    dto.setAttachments(Arrays.asList(fileData)); 
    MyEntity myEntity = mapper.map(dto, MyEntity.class); 
    assertEquals(fileData.getId(), myEntity.getAttachmentIds().get(0).toString()); 
} 

用一個例子消息失敗:

org.junit.ComparisonFailure: 
    Expected :56b0a9d110a937fc32a6db18 
    Actual :56b0a9d110a937fc32a6db19 

你可以找到整個測試和配置我在Github repo使用。

如何使這兩種方式的轉換器的工作?

回答

1

它用錯誤的推土機,導致未使用的自定義轉換器通過API映射當連接:https://github.com/DozerMapper/dozer/issues/242

所以,你可以通過XML提供任何映射:

<?xml version="1.0" encoding="UTF-8"?> 
<mappings xmlns="http://dozer.sourceforge.net" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xsi:schemaLocation="http://dozer.sourceforge.net 
      http://dozer.sourceforge.net/schema/beanmapping.xsd"> 
    <configuration> 
     <custom-converters> 
      <converter type="com.example.mapping.FileIdToFileDataConverter"> 
       <class-a>org.bson.types.ObjectId</class-a> 
       <class-b>com.example.mapping.entity.FileDataDto</class-b> 
      </converter> 
     </custom-converters> 
    </configuration> 
    <mapping> 
     <class-a>com.example.mapping.entity.MyEntity</class-a> 
     <class-b>com.example.mapping.entity.MyEntityDto</class-b> 
     <field> 
      <a>attachmentIds</a> 
      <b>attachments</b> 
      <a-hint>org.bson.types.ObjectId</a-hint> 
      <b-hint>com.example.mapping.entity.FileDataDto</b-hint> 
     </field> 
    </mapping> 
</mappings> 

然後

mapper.setMappingFiles(Arrays.asList("dozerconfig.xml")); 

或者,如果你不想使用XML,喲ü可以使用自己的ObjectIdFactory創建一個解決方法:

mapping(type(ObjectId.class).beanFactory(ObjectIdFactory.class), FileDataDto.class) 
    .fields(this_(), this_(), customConverter(FileIdToFileDataConverter.class)); 

,工廠類

public class ObjectIdFactory implements BeanFactory { 
    @Override 
    public Object createBean(Object source, Class<?> sourceClass, String targetBeanId) { 
     if (source == null) { 
      return null; 
     } 
     if (source instanceof ObjectId) { 
      return source; // we can return source, because it's immutable 
     } 
     if (source instanceof String) { 
      return new ObjectId((String) source); 
     } 
     if (source instanceof FileDataDto) { 
      return new ObjectId(((FileDataDto) source).getId()); 
     } 
     throw new MappingException("ObjectId should be of type ObjectId, String or FileDataDto"); 
    } 
} 

之所以這樣workaroud作品,爲什麼IDS不匹配

推土機默認情況下使用類的無參數構造函數實例化空值。 ObjectId是不可變的類,它的無參數構造函數根據時間戳創建新的實例。