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, manua
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.
If you want to ignore some fields, just add them after the targetObject
.
BeanUtils.copyProperties(sourceObj, targetObj, "propertyToIgnoreA", "propertyToIgnoreB", "propertyToIgnoreC");
Source: http://appsdeveloperblog.com/dto-to-entity-and-entity-to-dto-conversion/
I think this is the cleanest way. Remember to check the Javadoc for caveats!
Used mapstruct library. Additionally added the following in build.gradle
sourceSets {
main.java.srcDirs += "build/generated/sources/annotationProcessor/java/main/"
}
I can recommend to use mapstruct library:
<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:
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
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);
}
I think you are asking about where to write whole entity-->DTO conversion logic.
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
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
}
}
In my opinion
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.
This is an old question with accepted answer but though to update it with easy way of doing it using model-mapper 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.
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.
It should happen at controller because DTOs are meant to be exclusive transfer objects. I don't take my DTOs further way down.
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.
I prefer this approach because entities rarely change and data can be added / removed from DTOs as desired.
Detailed model mapper configuration and rules are described here