Should I Transform Entity (Persistent) Objects to Dto Objects

Spring Entities should convert to Dto in service?

We are talking about software architecture and as always when we are talking about software architecture there are a thousand ways of doing something and many opinions about what is the best way. But there is no best way, everything has advantages and disadvantages. Keep this in mind!

Typically you have different layers:

  • A persistence layer to store data
  • Business layer to operate on data
  • A presentation layer to expose data

Typically, each layer would use its own kind of objects:

  • Persistence Layer: Repositories, Entities
  • Business Layer: Services, Domain Objects
  • Presentation Layer: Controllers, DTOs

This means each layer would only work with its own objects and never ever pass them to another layer.

Why? Because you want each layer to be separated from the other layers. If you would use entities in your controller, your presentation would depend on how your data is stored. That's really bad. Your view has nothing to do with how the data is stored. It shouldn't even know that or how data is stored.

Think of that: You change your database model, e.g. you add a new column to one of your database tables. If you pass the entities to your controller (or worse: your controller exposes them as JSON), a change at the database would result in a change in your presentation. If the entities are directly exposed as JSON, this might even result in changes in JavaScript or some other clients which are using the JSON. So a simple change in the database might require a change in the JavaScript front end, because you couple your layers very tight. You definitely don't want that in a real project.

How? You doubt that this is practical, so just a small example of how to do that in (pseudo) code:

class Repository {
public Person loadById(Long id) {
PersonEntity entity = loadEntityById(id);
Person person = new Person();
person.setId(entity.getId());
person.setName(entity.getFirstName + " " + entity.getLastName());
return person;
}
}

In this example, your repository would use entities internally. No other layer knows or uses this entities! They are an implementation detail of this particular layer. So if the repository is asked to return a "person", it works on the entity, but it will return a domain object. So the domain layer which works with the repo is save in the case the entities need to be changed. And as you can see in the case of the name, the domain and the database might be different. While the database stores the name in first name and last name, the domain only know a single name. It's a detail of the persistence how it stores the name.

The same goes for controllers and DTOs, just another layer.

Conversion of DTO to entity and vice-versa

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

}

}

Domain object to persisting entity converting

First of all, that's quite a great idea to separate your persistent entity from your domain objects. I used to deal with setups where both approaches have been mixed together and that lead us to a complete mess afterwards.

The approach you're looking for is called 'Bean mapping'. There are a lot of such mappers around, Dozer seems to be the most widely used, but it's reflection-based and thus it's quite slow. Orika has good balance between performance and extensibility, but it also leads to some weird classloading issues in Java EE environment.

Most of bean mappers perform automatic mapping for equally named fields, extra conversions may be defined for 'simple transformations' you have mentioned above. Here's the example of Orika configuration for particular Web-to-DB entity mapping (with workaround for the classloading issue mentioned above applied): https://bitbucket.org/__jtalk/jacra/src/default/JAcraEJB/src/main/java/me/jtalk/jacra/utils/mapper/MappersRegistration.java

You can then use those mappers like:

@Inject
@UserMapper
private BoundMapperFacade<UserEntity, UserWeb> userMapper;
...
UserEntity entity = userMapper.mapReverse(userWeb);
mapper.map(entity);

Replace this persistent entity with a simple POJO or DTO object?

DO NOT put your Entity model into Controller method. You must create another model like MissionRequestModel for @RequestBody, and then convert your request model to your entity

public class MissionRequestModel {
private String name;
private String description;
}
@PostMapping("/ajouterMission")
@ResponseBody
public int ajouterMission(@RequestBody MissionRequestModel missionRequestModel) {
Mission mission = new Mission(missionRequestModel);
}

Persistence entities as data transfer objects

I would say that it is OK to do so (in fact the major advantage for these ORMs were to use these domain objects in different layers w/o having unnecessary DTOs) if you follow the following guidelines:

  1. You don't extend the session boundaries i.e., any changes related to database should always be done using the Data Access Layer you have defined and not through these passed objects in other layers.
  2. Any data that you need in other layer (layers above the Data Access Layer like Business Logic Layer and Presentation Layer) is pre-populated in these objects otherwise you will get exceptions according to the ORM behavior.
  3. Don't extend the session boundaries for resolving the issue mentioned in No. 2

DTOs vs Serializing Persisted Entities

DTOs. Use AutoMapper for object-to-object mapping



Related Topics



Leave a reply



Submit