将 DTO 转换为实体,反之亦然
Conversion of DTO to entity and vice-versa
我在我的 Web 应用程序中使用 Spring MVC
架构和 JPA
。在何处手动(即不使用任何框架)将数据传输对象 (DTO) 转换为 JPA 实体,反之亦然?
我认为
- 实体 -> DTO 转换应该在调度 jsp 页面之前在控制器中完成
- 在验证从 jsp 页面
返回的 DTO 后,也应在控制器中完成 DTO -> 实体转换
它使您可以更好地控制流程,并且您不必每次更改填充实体的某些逻辑时都更改 service/persistence 类。
我想你问的是在哪里编写整个实体-->DTO 转换逻辑。
喜欢你的实体
class StudentEntity {
int age ;
String name;
//getter
//setter
public StudentDTO _toConvertStudentDTO(){
StudentDTO dto = new StudentDTO();
//set dto values here from StudentEntity
return dto;
}
}
你的 DTO 应该是这样的
class StudentDTO {
int age ;
String name;
//getter
//setter
public StudentEntity _toConvertStudentEntity(){
StudentEntity entity = new StudentEntity();
//set entity values here from StudentDTO
return entity ;
}
}
你的控制器应该像
@Controller
class MyController {
public String my(){
//Call the conversion method here like
StudentEntity entity = myDao.getStudent(1);
StudentDTO dto = entity._toConvertStudentDTO();
//As vice versa
}
}
这是一个已接受答案的老问题,但可以使用模型映射器 API 以简单的方式对其进行更新。
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>0.7.4</version>
</dependency>
使用此 API,您可以避免手动 setter & 吸气剂,如已接受的答案中所述。
在我看来,这两种转换都应该在控制器中借助私有实用程序方法和使用 Java8 流的映射(如果交换了 DTO 集合)进行,如 this article 中所示。
它应该发生在控制器上,因为 DTO 是专有的传输对象。我不会进一步降低我的 DTO。
您在实体上编写服务和数据访问层代码,并在调用服务方法之前将 DTO 转换为实体,并在从控制器返回响应之前将实体转换为 DTO。
我更喜欢这种方法,因为实体很少更改,并且可以根据需要从 DTO 添加/删除数据。
描述了详细的模型映射器配置和规则here
我可以推荐使用 mapstruct 库:
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId>
<version>1.2.0.Final</version>
</dependency>
例如,如果您有这样一个实体:
public class Entity {
private Integer status;
private String someString;
private Date startDate;
private Date endDate;
// SKIPPED
和 DTO:
public class Dto {
private Boolean status;
private String someString;
private Long startDate;
private Long endDate;
// SKIPPED
那么在service层可以这样改造:
@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可以表示为:
@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);
}
我建议另一种没有额外依赖的方法:
import org.springframework.beans.BeanUtils
...
BeanUtils.copyProperties(sourceObject, targetObject);
可用于将 DTO 转换为实体,反之亦然,如果它们具有相同的 属性 类型和名称。
如果要忽略某些字段,只需将它们添加到 targetObject
之后。
BeanUtils.copyProperties(sourceObj, targetObj, "propertyToIgnoreA", "propertyToIgnoreB", "propertyToIgnoreC");
来源:http://appsdeveloperblog.com/dto-to-entity-and-entity-to-dto-conversion/
我认为这是最干净的方式。请记住查看 Javadoc 中的注意事项!
使用了 mapstruct 库。在 build.gradle
中另外添加了以下内容
sourceSets {
main.java.srcDirs += "build/generated/sources/annotationProcessor/java/main/"
}
我在我的 Web 应用程序中使用 Spring MVC
架构和 JPA
。在何处手动(即不使用任何框架)将数据传输对象 (DTO) 转换为 JPA 实体,反之亦然?
我认为
- 实体 -> DTO 转换应该在调度 jsp 页面之前在控制器中完成
- 在验证从 jsp 页面 返回的 DTO 后,也应在控制器中完成 DTO -> 实体转换
它使您可以更好地控制流程,并且您不必每次更改填充实体的某些逻辑时都更改 service/persistence 类。
我想你问的是在哪里编写整个实体-->DTO 转换逻辑。
喜欢你的实体
class StudentEntity {
int age ;
String name;
//getter
//setter
public StudentDTO _toConvertStudentDTO(){
StudentDTO dto = new StudentDTO();
//set dto values here from StudentEntity
return dto;
}
}
你的 DTO 应该是这样的
class StudentDTO {
int age ;
String name;
//getter
//setter
public StudentEntity _toConvertStudentEntity(){
StudentEntity entity = new StudentEntity();
//set entity values here from StudentDTO
return entity ;
}
}
你的控制器应该像
@Controller
class MyController {
public String my(){
//Call the conversion method here like
StudentEntity entity = myDao.getStudent(1);
StudentDTO dto = entity._toConvertStudentDTO();
//As vice versa
}
}
这是一个已接受答案的老问题,但可以使用模型映射器 API 以简单的方式对其进行更新。
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>0.7.4</version>
</dependency>
使用此 API,您可以避免手动 setter & 吸气剂,如已接受的答案中所述。
在我看来,这两种转换都应该在控制器中借助私有实用程序方法和使用 Java8 流的映射(如果交换了 DTO 集合)进行,如 this article 中所示。
它应该发生在控制器上,因为 DTO 是专有的传输对象。我不会进一步降低我的 DTO。
您在实体上编写服务和数据访问层代码,并在调用服务方法之前将 DTO 转换为实体,并在从控制器返回响应之前将实体转换为 DTO。
我更喜欢这种方法,因为实体很少更改,并且可以根据需要从 DTO 添加/删除数据。
描述了详细的模型映射器配置和规则here
我可以推荐使用 mapstruct 库:
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId>
<version>1.2.0.Final</version>
</dependency>
例如,如果您有这样一个实体:
public class Entity {
private Integer status;
private String someString;
private Date startDate;
private Date endDate;
// SKIPPED
和 DTO:
public class Dto {
private Boolean status;
private String someString;
private Long startDate;
private Long endDate;
// SKIPPED
那么在service层可以这样改造:
@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可以表示为:
@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);
}
我建议另一种没有额外依赖的方法:
import org.springframework.beans.BeanUtils
...
BeanUtils.copyProperties(sourceObject, targetObject);
可用于将 DTO 转换为实体,反之亦然,如果它们具有相同的 属性 类型和名称。
如果要忽略某些字段,只需将它们添加到 targetObject
之后。
BeanUtils.copyProperties(sourceObj, targetObj, "propertyToIgnoreA", "propertyToIgnoreB", "propertyToIgnoreC");
来源:http://appsdeveloperblog.com/dto-to-entity-and-entity-to-dto-conversion/
我认为这是最干净的方式。请记住查看 Javadoc 中的注意事项!
使用了 mapstruct 库。在 build.gradle
中另外添加了以下内容sourceSets {
main.java.srcDirs += "build/generated/sources/annotationProcessor/java/main/"
}