2

可能这可能是一个非常简单的问题,但在解决给定问题时我很迷茫。

我有一个名为 MediaResource 的实体,它有 id、imageName 等字段,另一方面,有 MediaResourceDTO 它有 imageName、byte[] resourceFile 等。

这个想法是从数据库中获取图像名称,在将 MediaResourceDTO 发送到客户端之前,我想将图像文件加载到 MediaResourceDTO 中。

我不知道如何从 MapStruct 实现这一点。

我看过几个@Before 和@After 的例子,但我不明白它的用例。

这是我的源代码: MediaResourceMapper

@Mapper(componentModel = "spring", uses = {VehicleMapper.class, })
public interface MediaResourceMapper {

    MediaResourceDTO mediaResourceToMediaResourceDTO(MediaResource mediaResource);

    List<MediaResourceDTO> mediaResourcesToMediaResourceDTOs(List<MediaResource> mediaResources);

    MediaResource mediaResourceDTOToMediaResource(MediaResourceDTO mediaResourceDTO);

    List<MediaResource> mediaResourceDTOsToMediaResources(List<MediaResourceDTO> mediaResourceDTOs);

    default MediaResource mediaResourceFromId(Long id) {
        if (id == null) {
            return null;
        }
        MediaResource mediaResource = new MediaResource();
        mediaResource.setId(id);
        return mediaResource;
    }
}

媒体资源实体

@Entity
@Table(name = "media_resource")
public class MediaResource implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "field_name")
    private String fieldName;

    @Column(name = "original_media_file_name")
    private String originalMediaFileName;

    @Column(name = "encrypted_media_file_name")
    private String encryptedMediaFileName;


    @Column(name = "resource_file_content_type", nullable = false)
    private String resourceFileContentType;

}

媒体资源DTO

public class MediaResourceDTO implements Serializable {

    private Long id;

    private String fieldName;

    private String originalMediaFileName;

    private String encryptedMediaFileName;

    @NotNull
    @Size(max = 20000000)
    @Lob
    private byte[] resourceFile;
    private String resourceFileContentType;

//Some getter and setters


    }

谢谢你。

4

2 回答 2

2

您可以通过提供装饰器来自定义映射。为此,您创建自己的类来实现映射器的接口并覆盖所需的映射方法:

public abstract class MediaResourceMapperDecorator implements MediaResourceMapper {

    private final MediaResourceMapper delegate;

    public MediaResourceMapperDecorator(MediaResourceMapper delegate) {
        this.delegate = delegate;
    }

    @Override
    MediaResourceDTO mediaResourceToMediaResourceDTO(MediaResource mediaResource) {
        // Let MapStruct do the basic mapping:
        final MediaResourceDTO dto = this.delegate.mediaResourceToMediaResourceDTO( mediaResource );

        // Then load and add the file to the DTO:
        dto.setResourceFile( loadMyFile( mediaResource.getOriginalMediaFileName() );

        return dto;
    }
}

然后你使用@DecoratedWith映射器上的注释来引用你的装饰器:

@Mapper(componentModel = "spring", uses = {VehicleMapper.class, })
@DecoratedWith(MediaResourceMapperDecorator.class)
public interface MediaResourceMapper {
    ...
于 2017-05-30T10:46:27.377 回答
1

您也可以通过告诉 MapStruct 它需要哪个服务来做到这一点,以便它可以将 映射filenameresourceFileStringbyte[]

您的服务 API:

public interface FileLoader {

    // @Named or some custom annotation annotated with @Qualifier can be
    // used in order to make sure that this will only be applied to the specified mapping
    @Named("fileMapper")
    byte[] loadFile(String filename);
}

您的映射器将如下所示:

@Mapper(componentModel = "spring", uses = {VehicleMapper.class, FileLoader.class })
public interface MediaResourceMapper {

    @Mapping(source = "originalMediaFileName", target = "resoruceFile", qualifiedByName = "fileMapper") // or qualifiedBy = CustomAnnotation.class
    MediaResourceDTO mediaResourceToMediaResourceDTO(MediaResource mediaResource);

   //The rest is the same
}

我个人更喜欢这种方法而不是装饰器,因为您将只有一个定义映射的地方,而 MapStruct 将处理其余部分。

有关基于限定符的映射的更多信息,请参见参考文档。

于 2017-05-30T19:33:08.840 回答