I have many issues with LazyLoadingException in a Spring web application wherever I try to access fields that are annotated with FetchType.LAZY
There is no session configured in Spring because the requirement is that the API should be stateless.
All the service layer methods have #Transactional annotations properly set.
However when I try to access the Lazy fields on any domain object, I get the famous LazyInitializationException (...) could not initialize proxy - no Session
I thought that Hibernate would automatically load the lazy fields when needed when I'm in a #Transactional method but it appears it doesn't.
I have spent several days looking for answers but nothing fits my needs. I found that Spring could be configured with openSessionInViewFilter but it appears to cause many issues, moreover I don't have any session.
How to automatically load lazy fields in #Transactionalannotated service methods with such a stateless API ?
I'm sure I'm missing something obvious here, but I'm not very familiar with Spring and Hibernate.
Please tell me if there are missing information in my question I should give you.
LazyInitializationExceptions are a code smell in a same way EAGER fetching is too.
First of all, the fetching policy should be query-based on a business case basis. Tha DAO layer is solely responsible for fetching the right associations, so:
You should use the FETCH directive for all many-to-one associations and at most one one-to-many association. If you try to JOIN FETCH more than one one-to-many associations, you'll get a Cartesian Product and your application performance will be affected.
If you need to fetch multiple collections, then a multi-level fetching is more appropriate.
You should ask yourself why you want to return entities from the DAO layer. Using DTOs is a much better alternative, as it reduces both the amount of data that's fetched from the DB and it doesn't leak the Entity abstraction into the UI layer.
Related
I'm currently in the process of migrating an API built in Laravel/PHP to Spring Boot and had a question on best practice/how to approach the problem.
In laravel, I have a User model, with 3 child relationships: roles, communities and profiles. In laravel, I'd use Resources to dictate the data I'm returning in an API response, for example a GET /id would return the user with all of the child relationships, where as on a GET / list operation, it would return the base model with no child relationships.
What is the best way to replicate this with Spring Boot JPA? I had looked into Jackson JsonViews, however this only seems to reduce the object returned by the API, rather than limiting the amount of SQL queries being ran.
Any suggestions are appreciated. Thanks!
If all of your relationships are Lazy (as they normally should be), then JsonViews is the right solution.
Whenever the joins are lazy, there is no query for the child data until the field has been accessed. So if the JsonView on / excludes the roles member of the User object, then the Json serializer will never call user.getRoles(), so the query is never run.
But if the JsonView for /id does include roles, then the serializer will have to call user.getRoles(), and at that time the query is run.
If you need even more optimization, then you can also attach an EntityGraph to a function on your repository like this:
public class UserRepository<User,Long> {
#EntityGraph(attributePaths = {"roles", "communities", "profiles"})
User getDetailedUserById(Long id);
}
This will force Eager loading for those otherwise lazy attributes, which means there will only be one query run.
I have been wondering how this anomaly should be handled:
DTO's should be converted in the controller, the service layer does not need to know about them.
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.
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.
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:
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?
You can mark controller method as transactional, there will be opened hibernate session after call to service level and so lazy loading will work.
DTOs are the model you should be working against from a layer above services. Only the service should know about the entity model. In simple degenerate cases the DTO model might look almost like the entity model which is why many people will just use the entity model. This works well until people get real requirements that will force them to change the way they use data. This is when the illusion that DTO = Entity falls apart.
A DTO is often a subset or a tranformation of the entity model. The point about the LazyInitializationException is a perfect example of when the illusion starts to crumble.
A service should return fully initialized DTOs i.e. not just some object that delegates to entity objects. There shouldn't be any lazy loading inovlved after a DTO was returned from a service. This means that you have to fetch exactly the state required for a DTO and wire that data into objects to be returned. Since that usually requires quite some boilerplate code and will sometimes result in having to duplicate logic, people tend to stick even longer to the DTO = Entity illusion by sprinkling some fetch joins here and there to make the LazyInitializationExceptions go away.
This is why I started the Blaze-Persistence Entity Views project which will give you the best of both worlds. Ease of use with less boilerplate, good performance and a safe model to avoid accidental errors. Maybe you want to give it a shot to see what it can do for you?
We are using JPA + Hibernate.
I have some Many-to-one mappings which are lazy loaded.
In Service, I Initiallize the Many-to-one objects by calling their getter method. but proxy gets assigned to parent VO and not actual VO Object.
My Question is, Is there any way in JPA to force to use no proxy Strategy.
My limitation here is i cant use Hibernate Objects or annotaions like #LazytoOne etc.
thanks in advance.
You cannot prevent Hibernate from using proxy objects there due to the fact that somehow it has to guarantee it's a lazy relation.
You have multiple choices:
Trigger the initialization Hibernate.initialize(parent.getChild()). Note that this is not the best way to do it and this also requires an active transaction.
Fetch the relation when fetching the entity itself. This can be done with the Fetch Joins. JPQL/HQL/Criteria API are capable of doing this.
Use read-only projections which contains only the data you need. For this particular case you can use Spring Data JPA as it comes with such a feature.
I suggest you to go with either option 2 or 3 as they are the most effective ways to do this.
Furher reading about lazy-loading here.
Do we have some set of rules when we should abstain of using FetchType.EAGER?
I have heard that some of JPA frameworks (eg. Hibernate) should resolve cyclic dependencies.
Do we have some advice when it comes risky to relay on frameworks?
Do StackOverflowError along with FetchType.EAGER is always about bug in framework(I mean if I have like 3 rows in two tables)?
One good reason to avoid FetchType.EAGER is that you can always enable eager fetching manually in JPQL (with JOIN FETCH), but you can't enable lazy fetching if you've set FetchType.EAGER.
EAGER:
Convenient, but slow
Use Eager when your parent class always need associate class.
LAZY:
More coding, but much more efficient
Basically lazy loading has more benefits than the eager alternative (performance, use of resources) . you should generally not configure it for eager fetching, unless you experience certain issues.
Sharing a domain instance accross different hibernate sessions (eg. when putting a domain class instance into the http session scope and accessing properties from it - such as a User)
When you're sure, you will access a certain relation property everytime (or most of the time) when an instance is fetched, it would also make sense to configure this relation for eager fetching.
eg: Relation Person and Address
Here, its not necessary that when i load Person entity i need to fetch Address all the time so you can keep lazy .
Conclusion
The EAGER fetching strategy is a code smell. Most often it’s used for simplicity sake without considering the long-term performance penalties. The fetching strategy should never be the entity mapping responsibility. Each business use case has different entity load requirements and therefore the fetching strategy should be delegated to each individual query.
The global fetch plan should only define LAZY associations, which are fetched on a per query basis. Combined with the always check generated queries strategy, the query based fetch plans can improve application performance and reduce maintaining costs.
I'm going to develop an application which uses a RESTfull service and also I'm going to use JPA/Hibernate as the ORM.
I have used these 2 technologies, but not in a single app.
Since client has no state, it is meaning less to use state full entities at the Data or Service Layer. And also there are bidirectional mappings as well.
I think CASCADE option of JPA will not work, rather than it will destroy the data, if the client is making an update.
So what I'm thinking is, detach objects before serve to the client and,
If there is an update (PUT) request, just passing the parent object and update only the parent. So I cannot use CASCADE option I suppose.
When it is a delete (DELETE) request, I have to do the CASCADE operations manually.
Also I think, making relationships between entities might be a problem.
Can anyone give a explanation about this scenario?
Is this approach correct?
Is there a best-practice on a situation like this?
Thanks!
Do not mix your business entities into the web layer.
I would recommend to decouple your business layer from the web layer creating new JAXB annotatted entities to return from your REST controller.
If you want to make easy your work, there are a lot of libraries that can copy 1 bean to another. For example the Apache BeanUtils.class.