xyz
xyz

Reputation: 2160

Conversion of DTO to entity and vice-versa

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)?

Upvotes: 43

Views: 114456

Answers (6)

Sabir Khan
Sabir Khan

Reputation: 10132

This is an old question with accepted answer but thought 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

Upvotes: 47

WesternGun
WesternGun

Reputation: 12728

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!

Upvotes: 30

bhagyashree1990
bhagyashree1990

Reputation: 61

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

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

Upvotes: 0

user1134181
user1134181

Reputation:

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);
}

Upvotes: 17

NIrav Modi
NIrav Modi

Reputation: 6962

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

    }

}

Upvotes: 15

segaurav
segaurav

Reputation: 217

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

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.

Upvotes: 7

Related Questions