Do JPA entities and DTOs belong to Service or Spring Repository layer

3.1k views Asked by At

I want to write a JPA application, but I have problems understanding the repository and service concepts:

Consider we have 3 entities: A, B and C.

Entity A needs to have B and C set: A.setB(B), A.setC(C) before it is saved.

Also for read, I want to return only DTOs since they will free me from LazyInitializationException, Open Session In View Anti-Pattern, etc, and for modifying data I will use entities ( these guidelines are also described in this book High-Performance Java Persistence).

First of all, the user will make a HTTP POST with some data which will be converted into ABCGuiObject. The REST controller will call serviceA.save(ABCGuiObject).

Persist options:

Option #1 - The service will create 3 objects A, B ,C and pass them to repositoryA.save(A,B,C). The repositoryA will do inside a.setB and a.setC.

Option #2 - The service will create 3 objects A, B ,C, do a.setB and a.setC and call repositoryA.save(A).

DTO retrieval

I would like to write a JPQL query to get some DTO. I do not want to convert entities to DTO, but retrieve them directly with JPQL.

Option #1 - repositoryA will return directly a DTO.

Option #2 - the service will pass a JPQL query to the repositoryA, which will have a general query method which returns a DTO.

What approaches do you recommend?

4

There are 4 answers

5
Vlad Mihalcea On BEST ANSWER

Write data

The Service layer should construct the graph of entities A, B and C and connect them accordingly (a.setB and a.setC) and pass A, B and C to the Repository. If you have one-to-many associations, you can cascade entity state transitions.

Read data

If you want to return DTOs, you are better off fetching DTOs directly from JPA and Hibernate. So, you have two options:

3
isah On

This is a subjective thing but I'll share my opinion. For Persist Options, I recommend Option #2. The repository ideally should just do "repository" duties, the service or if too complex you can delegate to a factory to build the A entity.

For the DTO retrieval, I would issue queries to retrieve the entities(so the repository would always return entities), and transform them to DTO. Someone may need the same repository feature and they can choose to transform to DTO, instead of writing another JPQL with DTO query.

2
Peter Šály On

Persist option 2.

DTO objects are usually loading lazy fields. This can harm performance if you don't write separate query/mapping for different use cases. DO NOT USE DTO, instead initialize lazy fields per use case to avoid LazyIntializationException. Also it will save you lot work with mapping from and into entity for saving.

0
Christian Beikov On

Regarding the persisting, I'd go with option 2 but not for all service related actions. If you have simple actions like e.g. addComment, enable/disable then it might be better to only pass ids and let the service get it's hands on the entity itself.

For DTOs I suggest you give Blaze-Persistence Entity Views a look to see how easy the DTO pattern can be implemented. Here is a nice article about getting started with it.