Many spring boot applications use Spring MVC to provide RESTful APIs or create a GUI for a web browser.
These applications frequently use DTO (data transfer objects) in the controller layer instead of using JPA @Entity
classes everywhere.
Is this cargo cult programming or a good idea? My opinion is that it's a good idea, except for very tiny applications.
I'm in favor of:
@Controller
layer share DTOs@Controller
layer to/from the @Service
layer.@Service
layer uses the DTOs to build @Entity
objects for use with the JPA @Repository
objects. Lazy loading in JPA is sweet.
@Service
classes loop through the @Entity
objects to build the DTOs. This way the logic around pagination and lazy loading is isolated
to the @Service
classes.There are many reasons
Andreas's answer is great. It acknowledges that in small projects people sometime use @Entity
classes in the MVC layer and the importance of not doing that as projects get larger.
I'll quote Andreas's answer below, in the rest of this post, (because it's a great answer):
In today programming with Spring MVC and interactive UIs, there are really 4 layers to a web application:
UI Layer (Web Browser, JavaScript)
MVC Controller, i.e. Spring components annotated with @Controller
Service Layer, i.e. Spring components annotated with @Service
Data Access Layer, i.e. Spring components annotated with @Repository
Every time one of these layers interact with the underlying layer, they need to send/receive data, which generally are POJOs, to transfer the data between layers. These POJOs are DTOs, aka Data Transfer Objects.
Only DTOs should be used between layers, and they are not necessarily the same, e.g. the Service Layer may apply business logic to DTOs received from the Data Access Layer, so the DTOs of the Service Layer API is different from the Data Access Layer API. Similarly, the Controller may rearrange the data to prepare it for presentation (grouping, summaries, ...), so the data sent to the web browser is different from the data received from the Service Layer.
With full abstraction, the Data Access Layer's API should not reflect the technology of the Data Access, i.e. whether it is using JDBC, JPA, NoSQL, a web service, or some other means of storing/retrieving the data. This means that Entity classes shouldn't make it outside the Data Access Layer.
Most projects don't need that level of abstraction, so it is common for a DTO to be an Entity class, and to flow all the way from the Data Access Layer to the Controller, where it is used either by a View, or is send to the web browser, encoded as JSON.
It depends on the size and complexity of the project. The bigger the project, the more important it becomes to make each layer as abstract/standalone as possible.