Java DTO 与实体的转换,反之亦然

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28703401/
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-08-11 06:40:28  来源:igfitidea点击:

Conversion of DTO to entity and vice-versa

javaspring-mvcjpa

提问by xyz

I am using Spring MVCarchitecture with JPAin my web application. Where to convert data transfer object (DTO) to JPA entity and vice-versa, manually (that is, without using any framework)?

我在我的 Web 应用程序中使用Spring MVC架构JPA。在哪里手动(即不使用任何框架)将数据传输对象 (DTO) 转换为 JPA 实体,反之亦然?

采纳答案by NIrav Modi

I think you are asking about where to write whole entity-->DTO conversion logic.

我想您是在问在哪里编写整个实体--> DTO 转换逻辑。

Like Your entity

喜欢你的实体

class StudentEntity {
 int age ;
 String name;

 //getter
 //setter

 public StudentDTO _toConvertStudentDTO(){
    StudentDTO dto = new StudentDTO();
    //set dto values here from StudentEntity
    return dto;
 }

}

Your DTO Should be like

你的 DTO 应该像

class StudentDTO  {
 int age ;
 String name;

 //getter
 //setter

 public StudentEntity _toConvertStudentEntity(){
    StudentEntity entity = new StudentEntity();
    //set entity values here from StudentDTO
    return entity ;
 }

}

And Your Controller should be like

你的控制器应该像

@Controller
class MyController {

    public String my(){

    //Call the conversion method here like
    StudentEntity entity = myDao.getStudent(1);
    StudentDTO dto = entity._toConvertStudentDTO();

    //As vice versa

    }

}

回答by segaurav

In my opinion

在我看来

  • the Entity -> DTO conversion should be done in the Controller before dispatching the jsp page
  • the DTO -> Entity conversion should be done in the Controller as well after validating the DTO returned from the jsp page
  • Entity -> DTO 转换应该在调度jsp页面之前在Controller中完成
  • 在验证从 jsp 页面返回的 DTO 之后,DTO -> 实体转换也应该在控制器中完成

Its gives you more control over the process and you do not have to change the service/persistence classes every time some logic populating the Entity is changed.

它使您可以更好地控制流程,并且每次更改填充实体的某些逻辑时,您都不必更改服务/持久性类。

回答by Sabir Khan

This is an old question with accepted answer but though to update it with easy way of doing it using model-mapper API.

这是一个老问题,答案已被接受,但尽管使用模型映射器 API 以简单的方式更新它。

<dependency>
    <groupId>org.modelmapper</groupId>
    <artifactId>modelmapper</artifactId>
    <version>0.7.4</version>
</dependency>

Using this API, you avoid manual setter & getters as explained in accepted answer.

使用此 API,您可以避免手动设置器和吸气器,如已接受的答案中所述。

In my opinion, both conversions should happen at controller with the help of private utility methods and using Java8 stream's map ( if a Collection of DTOs is exchanged ) like illustrated in this article.

在我看来,这两种转换都应该在控制器的私有实用方法的帮助下发生,并使用 Java8 流的映射(如果交换了 DTO 的集合),如本文所示

It should happen at controller because DTOs are meant to be exclusive transfer objects. I don't take my DTOs further way down.

它应该发生在控制器上,因为 DTO 是独占传输对象。我不会进一步降低我的 DTO。

You code your service & data access layers on entities and convert DTOs to entities before calling service methods & convert entities to DTOs before returning response from controller.

您在实体上编码服务和数据访问层,并在调用服务方法之前将 DTO 转换为实体,并在从控制器返回响应之前将实体转换为 DTO。

I prefer this approach because entities rarely change and data can be added / removed from DTOs as desired.

我更喜欢这种方法,因为实体很少更改,并且可以根据需要从 DTO 添加/删除数据。

Detailed model mapper configuration and rules are described here

此处描述详细的模型映射器配置和规则

回答by Sabir Khan

I can recommend to use mapstructlibrary:

我可以推荐使用mapstruct库:

<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct-jdk8</artifactId>
    <version>1.2.0.Final</version>
</dependency>

For example, if you have such an entity:

例如,如果您有这样一个实体:

public class Entity {
    private Integer status;
    private String someString;
    private Date startDate;
    private Date endDate;

    // SKIPPED

And DTO:

和 DTO:

public class Dto {
    private Boolean status;
    private String someString;
    private Long startDate;
    private Long endDate;

    // SKIPPED

Then the transformation can be done in the service layer by this way:

那么可以通过这种方式在服务层进行转换:

@Service
public class SomeServiceImpl implements SomeService {

    @Autowired
    SomeDao someDao;

    @Autowired
    SomeMapper someMapper;


    public Dto getSomething(SomeRequest request) throws SomeException {
        return someDao.getSomething(request.getSomeData())
                .map(SomeMapper::mapEntityToDto)
                .orElseThrow(() -> new SomeException("..."));
    }

Mapper can be represented as follows:

Mapper 可以表示如下:

@Mapper 
public interface SomeMapper {
    @Mappings(
            {@Mapping(target = "entity", 
                      expression = "java(entity.getStatus() == 1 ? Boolean.TRUE : Boolean.FALSE)"),
             @Mapping(target = "endDate", source = "endDate"),
             @Mapping(target = "startDate", source = "startDate")
            })

    Dto mapEntityToDto(Entity entity);
}

回答by WesternGun

I suggest another approach without extra dependency:

我建议另一种没有额外依赖的方法:

import org.springframework.beans.BeanUtils
...
BeanUtils.copyProperties(sourceObject, targetObject);

Can be used to convert DTO to entity, or vice-versa, if they have same property types and names.

可用于将 DTO 转换为实体,反之亦然,如果它们具有相同的属性类型和名称。

If you want to ignore some fields, just add them after the targetObject.

如果您想忽略某些字段,只需将它们添加到targetObject.

BeanUtils.copyProperties(sourceObj, targetObj, "propertyToIgnoreA", "propertyToIgnoreB", "propertyToIgnoreC");

Source: http://appsdeveloperblog.com/dto-to-entity-and-entity-to-dto-conversion/

来源:http: //appsdeveloperblog.com/dto-to-entity-and-entity-to-dto-conversion/

I think this is the cleanest way.

我认为这是最干净的方式。

回答by bhagyashree1990

Used mapstruct library. Additionally added the following in build.gradle

使用 mapstruct 库。另外在 build.gradle 中添加了以下内容

sourceSets {
    main.java.srcDirs += "build/generated/sources/annotationProcessor/java/main/"
}