java 如何将 DTO 映射到现有的 JPA 实体?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/46536060/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 09:15:28  来源:igfitidea点击:

How to map a DTO to an existing JPA entity?

javaspringhibernatemodelmapper

提问by dyslexit

I'm trying to map a Java DTO object to an existing JPA entity object without having to do something like the following:

我正在尝试将 Java DTO 对象映射到现有的 JPA 实体对象,而无需执行以下操作:

public MyEntity mapToMyEntity(SomeDTO dto, MyEntity entity) {
    entity.setField1(dto.getField1());
    entity.setField2(dto.getField2());
    ...
    entity.setField20(dto.getField20());

    return entity;
}

Up to now I've been using ModelMapperlike so: MyEntity entity = modelMapper.map(dto, SomeDTO.class);, but what I'm trying to do instead is map to an existingentity object rather than creating a newentity object from a DTO. I've looked through the ModelMapper manual and couldn't find how to map without creating a new object. Am I stuck adding each member variable manually for each entity object I might have?

到目前为止,我一直像这样使用ModelMapper:,MyEntity entity = modelMapper.map(dto, SomeDTO.class);但我想做的是映射到现有的实体对象,而不是从 DTO创建新的实体对象。我浏览了 ModelMapper 手册,找不到如何在不创建新对象的情况下进行映射。我是否坚持为我可能拥有的每个实体对象手动添加每个成员变量?

回答by Sahin Yanl?k

You can use dozer mapper or gson.

您可以使用推土机映射器或 gson。

DozerMapper ex:

DozerMapper 前:

Mapper mapper = DozerBeanMapperBuilder.createDefault();
DestinationObject destObject = mapper.map(sourceObject,DestinationClassName.class);

You can check github pagefor more information

您可以查看github 页面以获取更多信息

回答by Andrew Nepogoda

You can define next class:

您可以定义下一个类:

public class ObjectMapperUtils {

    private static ModelMapper modelMapper = new ModelMapper();

    /**
     * Model mapper property setting are specified in the following block.
     * Default property matching strategy is set to Strict see {@link MatchingStrategies}
     * Custom mappings are added using {@link ModelMapper#addMappings(PropertyMap)}
     */
    static {
        modelMapper = new ModelMapper();
        modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
    }

    /**
     * Hide from public usage.
     */
    private ObjectMapperUtils() {
    }

    /**
     * <p>Note: outClass object must have default constructor with no arguments</p>
     *
     * @param <D>      type of result object.
     * @param <T>      type of source object to map from.
     * @param entity   entity that needs to be mapped.
     * @param outClass class of result object.
     * @return new object of <code>outClass</code> type.
     */
    public static <D, T> D map(final T entity, Class<D> outClass) {
        return modelMapper.map(entity, outClass);
    }

    /**
     * <p>Note: outClass object must have default constructor with no arguments</p>
     *
     * @param entityList list of entities that needs to be mapped
     * @param outCLass   class of result list element
     * @param <D>        type of objects in result list
     * @param <T>        type of entity in <code>entityList</code>
     * @return list of mapped object with <code><D></code> type.
     */
    public static <D, T> List<D> mapAll(final Collection<T> entityList, Class<D> outCLass) {
        return entityList.stream()
                .map(entity -> map(entity, outCLass))
                .collect(Collectors.toList());
    }

    /**
     * Maps {@code source} to {@code destination}.
     *
     * @param source      object to map from
     * @param destination object to map to
     */
    public static <S, D> D map(final S source, D destination) {
        modelMapper.map(source, destination);
        return destination;
    }
}

And use it for your needs:

并根据您的需要使用它:

MyEntity entity = ObjectMapperUtils.map(dto, existingEntity);

回答by pirho

Currently ModelMappersupports mapping also to an existing object.

目前ModelMapper还支持映射到现有对象。

It is possible to do the following (for a pseudo Spring example):

可以执行以下操作(对于伪 Spring 示例):

MyEntity mye = repository.finById(id);
ModelMapper mm = new ModelMapper();    
mm.map(myDTO, mye);
repository.save(mye):

I am using version 2.3.1 but earlier versions might support this functionality also

我使用的是 2.3.1 版,但早期版本可能也支持此功能

回答by Dilnei Cunha

Translated from Portuguese

翻译自葡萄牙语

https://pt.stackoverflow.com/questions/166438/dto-assembler-como-utiliza-lo-realmente

https://pt.stackoverflow.com/questions/166438/dto-assembler-como-utiliza-lo-realmente

Use Pattern Assembler: You could convert Entity to DTO through the assembler pattern but it is wrong (I think), it breaks the sense of the DTO which is a standard for transferring objects. See that it can be composed by of several entities. The correct thing is to use set methods of the instances of the objects in the classes of services, taking the DTO's and assembling them as entities, it is simply because you are working correctly with the standard.

使用模式汇编器:您可以通过汇编器模式将实体转换为 DTO,但这是错误的(我认为),它打破了作为传输对象标准的 DTO 的意义。看到它可以由几个实体组成。正确的做法是使用服务类中对象实例的 set 方法,将 DTO 组合为实体,这仅仅是因为您正确地使用了标准。

But it has a way that even if it being wrong it would work, but only a 1 x 1 association between entity x DTO, use Guava function.

但它有一种方法,即使它是错误的,它也能工作,但实体 x DTO 之间只有 1 x 1 关联,使用 Guava 函数。

Eg: to convert Translate to transform into objects and lists with

例如:将 Translate 转换为对象和列表

import java.util.ArrayList;
import java.util.List;
import com.google.common.base.Function;

    /**
     * Classe de transforma??o para popular os dados em DTOs, seguindo o pattern
     * Transfer Object Assembler.
     */
    public class Transformer {

        /**
         * Executa a transforma??o de um objeto para um DTO.
         * 
         * @param from
         * @param function
         * @return <F, T> T
         */
        public static <F, T> T transform(F from, Function<? super F, ? extends T> function) {
            return (from == null) ? null : function.apply(from);
        }

        /**
         * Executa a transforma??o de uma lista de objetos para uma lista de DTOs.
         * 
         * @param fromList
         * @param function
         * @return <F, T> List<T>
         */
        public static <F, T> List<T> transform(List<F> source, Function<? super F, ? extends T> function) {
            List<T> out = new ArrayList<>(source.size());

            for (F from : source) {
                out.add(function.apply(from));
            }    
            return out;
        }    
    }

Pattern assembler:

模式汇编器:

import java.util.List;
import br.com.myapp.model.dto.AuthUserDTO;
import br.com.myapp.model.entity.AuthUser;
import com.google.common.base.Function;
import com.google.common.collect.Lists;

/**
 * Classe que transforma entidade USUARIOS em DTO.
 * 
 * @author Dilnei Cunha
 */
public class AuthUserDTOAssembler implements Function<AuthUser, AuthUserDTO>{

    /**
     * Método responsável por fazer a convers?o da entidade USUARIOS em um AuthUserDTO.
     */
@Override
public AuthUserDTO apply(AuthUser e) {

    AuthGroupDTO groupDTO = Transformer.transform(e.getAuthGroup(), new  AuthGroupDTOAssembler());

    return new AuthUserDTO(e.getId(),
                       e.getName(),
                       e.getPassword(),
                       e.getEmail(),
                       e.getCreationDate(),
                       e.getLastModificationdate(),
                       e.getLastAccessDate(),
                       e.getAtivo(),
                       e.getUserName(),
                       e.getRamal(),
                       groupDTO);
    }
}

What would be the service that would use these patterns ...

使用这些模式的服务是什么......

/**
 * Método responsável por buscar um AuthUserDTO pelo ID do usuário.
 */
@Override
public AuthUserDTO findById(Long id) {
    return Transformer.transform(authUserRepository.findUserById(id), new AuthUserDTOAssembler());
}

Now let's do the inverse process of turning one or a list of DTOs into objects, but keep in mind that the association was 1x1. To do this, simply reverse the objects in the implementation of the function, eg:

现在让我们执行将一个或一组 DTO 转换为对象的逆过程,但请记住,关联是 1x1。为此,只需在函数的实现中反转对象,例如:

import java.util.List;
import br.com.myapp.model.dto.AuthUserDTO;
import br.com.myapp.model.entity.AuthUser;
import com.google.common.base.Function;
import com.google.common.collect.Lists;

/**
 * @author Dilnei Cunha
 */
public class AuthUserAssembler implements Function<AuthUserDTO, AuthUser>{

@Override
public AuthUser apply(AuthUserDTO e) {

        AuthGroup group = Transformer.transform(e.getAuthGroupDTO(), new  AuthGroupAssembler());

        return new AuthUser(e.getId(),
                           e.getName(),
                           e.getPassword(),
                           e.getEmail(),
                           e.getCreationDate(),
                           e.getLastModificationdate(),
                           e.getLastAccessDate(),
                           e.getAtivo(),
                           e.getUserName(),
                           e.getRamal(),
                           group);
        }
    }