我在我的网络应用程序中使用Spring MVC
架构和JPA
。
手动将DTO转换为实体,反之亦然(不使用任何框架)?
答案 0 :(得分:12)
这是一个老问题,已接受答案但是要使用模型映射器API以简单的方式更新它。
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>0.7.4</version>
</dependency>
使用此API,您可以避免使用手动设置器和在接受的答案中解释的吸气剂。
在我看来,两个转换都应该在私有实用程序方法的帮助下进行,并使用Java8流的映射(如果交换了DTO集合),如this article中所示。
它应该发生在控制器上,因为DTO应该是独占的传输对象。我没有把我的DTO进一步向下。
您为自己的服务编码&amp;实体上的数据访问层,并在调用服务方法之前将DTO转换为实体。在从控制器返回响应之前将实体转换为DTO。
我更喜欢这种方法,因为实体很少更改,并且可以根据需要从DTO添加/删除数据。
详细的模型映射器配置和规则描述为here
答案 1 :(得分:8)
我认为你在询问在哪里写整个实体 - &gt; 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
}
}
答案 2 :(得分:7)
在我看来
它使您可以更好地控制进程,并且每次填充实体的某些逻辑发生更改时,您不必更改服务/持久性类。
答案 3 :(得分:5)
我可以建议使用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
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
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);
}
答案 4 :(得分:3)
我建议另一种无需额外依赖的方法:
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/
我认为这是最干净的方法。
答案 5 :(得分:0)
使用的mapstruct库。另外在build.gradle中添加了以下内容
sourceSets {
main.java.srcDirs += "build/generated/sources/annotationProcessor/java/main/"
}