Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Transaction Boundary and DTO conversion with JPA

I have been wondering how this anomaly should be handled:

  1. DTO's should be converted in the controller, the service layer does not need to know about them.
  2. Transaction boundaries are defined by the service layer.

But how do you avoid a JPA LazyInitialization exception then? The DTO conversion might need Lazy Fetched data but is unable to as the transaction was handled by the service layer.

There are ways I can think of, but all of them are ugly. Putting the DTO conversion in the service layer seems the best to me now.

like image 848
Juru Avatar asked Mar 22 '17 16:03

Juru


People also ask

Why do we use DTO in spring boot?

In Spring Framework, Data Transfer Object (DTO) is an object that carries data between processes. When you're working with a remote interface, each call is expensive. As a result, you need to reduce the number of calls. The solution is to create a Data Transfer Object that can hold all the data for the call.

What is a transaction JPA?

A transaction is a set of operations that either fail or succeed as a unit. Transactions are a fundamental part of persistence. A database transaction consists of a set of SQL DML (Data Manipulation Language) operations that are committed or rolled back as a single unit.

What is the difference between DTO and entity?

Difference between DTO & Entity: Entity is class mapped to table. Dto is class mapped to "view" layer mostly. What needed to store is entity & which needed to 'show' on web page is DTO.


2 Answers

Yes, definitely it is better to manipulate DTOs in the service layer. This is especially true when updating entities with changes contained in DTOs, as otherwise you would need to get and update detached entities, pass them to service, merge them again into the persistence context, etc.

"DTO's should be converted in the controller, the service layer does not need to know about them."

Instead of this, I would say the better rule of thumb is that controllers do not need to know about entities. But you can use detached entities instead of DTOs for simple cases to avoid creating lots of small DTO classes, although I personally always use DTOs just to be consistent and to make later changes easier.

like image 56
Dragan Bozanovic Avatar answered Oct 12 '22 18:10

Dragan Bozanovic


Raised 'LazyInitializationException' is just signal that some parts of data were not loaded, so the best solution will be to make multiple calls from controller method to service level and fetch all required fields for DTO.

Less elegant options are:

  1. Its possible to detect fields that were not loaded via 'org.hibernate.Hibernate.isInitialized' method and skip them during DTO build, see here full sample: How to test whether lazy loaded JPA collection is initialized?

  2. You can mark controller method as transactional, there will be opened hibernate session after call to service level and so lazy loading will work.

like image 37
Alex Chernyshev Avatar answered Oct 12 '22 19:10

Alex Chernyshev