Currently, all REST applications I work with have a three-layered architecture:
- Persistence -> Contains "entity" classes with JPA annotations / Spring Data JPA repositories
- Core -> Contains "model" classes which are POJOs, along with "service" classes that perform business logic by using repositories from the persistence layer to serialize / de-serialize models to/from entities.
- API -> Contains DTOs and controller classes, along with mappers.
The application essentially models the same "concept" or "model" three times in three difference classes. As an example, if I had a "Product" class, I would have:
- ProductEntity -> JPA specific annotations
- Product -> Plain POJO
- ProductDTO -> API response
along with mappers to map between the different layers.
This architecture feels clean and right, but in practice, maintaining three separate classes for the same concept, along with fighting with mappers makes a non-insignificant amount of overhead, and it also opens up the possibility of not keeping fields in sync between the different layers.
I definitely want to at least keep separate classes between entities and DTOs, but I'm not convinced I should have the "model" layer. The issue with that though is that the business layer then would also directly manipulate JPA entities, and calling getters on JPA entities can create database calls.
Is there a best practice / industry standard for this? I'm leaning towards starting with entity and DTO classes, and only adding intermediate "model" classes if I need ot add state / data to a model and it wouldn't be appropriate to put it on the JPA entity.