JPA+Hibernate force JPA not to use Proxies on Lazy loading - java

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.

Related

Best practice for Hibernate lazy properties initialization in MVC?

Let's say I use some entity, in pseudocode: Article { id, author, text, date } with all properties initialized lazily. I have repository method:
#Transactional
Article loadArticle(int id) {
return articeRepository.find(id);
}
which is used by different controllers. PreviewController requires author and date. ViewController requires text and date.
Should I pass boolean parameters initAuthor, initText, initDate to loadArticle() method to call Hibernate.initialize() for each property there? Or should I move #Transactional to controllers' methods? What are the best practices dealing with lazy initialization?
If you are aiming to have a highly performant data access layer, then you should keep one thing in your mind: every use-case is different thus needs different kind of data.
What I wanted to suggest with this is that you want to have different methods for different use-cases, which fetches only the data it needs.
There are multiple ways to do this:
Fetching the entity relation with a fetch join
Create read-only projections
I prefer the latter as it clearly shows that it's for showing data rather than modifying it.
For projections, Spring Data JPA can help as it has an out-of-the-box solution for it which is basically defining an interface.
If you use Hibernate.initialize() or any other way to trigger loading an entity relation, practically you will trigger a database query. If you think about let's say 100 entities, that means you will execute 101 queries. Use fetching or read-only projections.

In Hibernate JPA how to transparently solve " failed to lazily initialize a collection of role " exception

I am migrating a huge project from Eclipselink to Hibernate JPA that running on Wildfly 10.0
Once moved to Hibernate I got the famous exception " failed to lazily initialize a collection of role "
I found many solutions for this issue like these suggestions on this Question as well as the old OpenSessionInView method.
But these solutions are somehow outdated, and needs some changes on my running existing code that use eclipselink.
Is their a newer, modern, transparent solution that can save my time ?
Note: I am not using spring (only JPA and EJB) .
I think you are looking for the hibernate.enable_lazy_load_no_trans configuration property. But that's an Anti-Pattern. Just because other JPA providers use it, it does not mean that it is efficient as well, or it's even appropriate.
Another bad way of "fixing" the LazyInitializationException is the Open Session in View, which is also an Anti-Pattern.
The best way to handle LazyInitializationException is to JOIN FETCH all one-to-one and many-to-one associations and up to a single one-to-many association.
If you need to fetch multiple one-to-many or many-to-many associations, then the first one should be JOIN FETCH-ed, while the subsequent ones should be initialized with a separate query. You can either navigate the association to trigger the initialization or use Hibernate#initialize.

Whats the safest way to remove lazy initialization proxies generated by Hibernate?

I would like to keep the Parent/Child relationship but when I parse through the Parent Object I don't want to fetch the child elements.
Proxies are generated so that Hibernate can intercept calls to uninitialized associations and try fetching them on-demand.
The LazyInitializationException is a code smell. You get it because you haven't properly initialized all the required entity associations prior to closing a Session. Switching to EAGER associations is also a bad idea because the fetching policy is a query responsibility.
Try to reduce the number of associations if you don't need them and use queries instead. You can build an application with just many-to-one associations (mirroring the FK relations) and instead of one-to-many associations you can have DAO methods.
As for this statement:
I would like to keep the Parent/Child relationship but when I parse
through the Parent Object I don't want to fetch the child elements.
If you keep the Parent/Child relationship you always need to load the association prior to using it. Trying to remove the proxies sounds like you are trying to hack a solution instead of properly design your application layers.
So Proxies are fine and they allow you to improve the application performance, because you don't always fetch all associations when you try to access a root entity.
To disable proxies you just have to annotate your entities with the Proxy annotation:
#Proxy(lazy=false)

Hibernate FetchType.LAZY without session

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.

Flex Blaze DS and JPA - lazy-loading issues

I am developing an application in Flex, using Blaze DS to communicate with a Java back-end, which provides persistence via JPA (Eclipse Link).
I am encountering issues when passing JPA entities to Flex via Blaze DS. Blaze DS uses reflection to convert the JPA entity into an ObjectProxy (effectively a HashMap) by calling all getter methods on the entity. This includes any lazy-initialised one/many-to-many relationships.
You can probably see where I am going. If I pass a single object through JPA this will call all one/many-to-many methods on this object. For each returned object if they have one/many-to-many relationships they will be called too. As such, by passing back a single JPA entity I actually end up doing multiple database calls and passing all related entries back as a single ObjectProxy instance!
My solution to date is to create a translator to convert each entity to an ObjectProxy and vice-versa. This is clearly cumbersome and there must be a better way.
Thoughts please?
As an alternative, you could consider using GraniteDS instead of BlazeDS: GraniteDS has a much more powerful data management stack than BlazeDS (it competes more with LCDS) and fully support lazy-loading for all major JPA engines: Hibernate, EclipseLink, OpenJPA, etc.
Moreover, GraniteDS has a great client-side transparent lazy loading feature and even a so-called reverse lazy-loading mechanism.
And you don't need any kind of intermediate DTOs: it serializes JPA entities as is and uses code-generated ActionScript beans on the client-side to keep their initialization states.
Unfortunately, lazy-loading is not easy to accomplish with Flash clients. There are some working solutions, like dpHibernate, but so far all the different solutions I have tested fall short of what you would expect in terms of performance and ease of use.
So in my experience, it is the best and most reliable solution to always use DTOs, which adds the benefit of cleanly separating the database and view layers. This necessitates, though, that you implement either eager loading, or a second server round trip to resolve your many-to-many relations, as well as a good deal more boilerplate code to copy the DAO and DTO field values.
Which one to choose depends on your use case: Sometimes getting only the main object's fields might be enough, then you could simply omit the List of related objects from your DTO (transfer only those values you need for your query). Sometimes you may actually need the entire list of related entities, and then you could get it via eager loading, or by setting up a second remote object to find only the list.
EclipseLink also provides a copyObject() API that allows you to give a copy group of exactly what attribute you want. You could then use this copy to avoid having the relationships that you do not want.
If you have a detached object, you could just null out the fields that you do not want as well, or use a DTO.

Categories