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
Conversion of DTO to entity and vice-versa
提问by xyz
I am using Spring MVC
architecture with JPA
in 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/"
}