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

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)

Related

Override lazy OneToMany relationship

Have an entity with a OneToMany relationship in Spring Data that I would need to filter by a specific column. I've been unable to find a satisfying solution to get it with a single query (both parent entity and the filtered OneToMany in one go) so I'm now thinking in having it lazy fetched and after getting the parent entity, have a separate query to retrieve the linked entities and just using a setter to link them together (ie: parent.setChildren(childrenRepository.findAllBy...)).
Question is: would this effectively disable any future trigger to the lazy fetch so my manually set children would remain? Use case here is to add these children manually in certain cases, and using the default lazy fetch when the conditions don't apply.
I tested this and seems to be working as intended, but could not find information on when the lazy fetch should be triggered as to make sure my logic would work in any scenario (is it disabled as soon as the setter is invoked? is this documented anywhere?)
Thanks in advance.

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

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.

Hibernate manyToOne filter on base entity

I have an entity "Event" that has a ManyToOne relationship with the entity "Organization". So an Organization can have multiple events.
What I originally wanted to do was to filter the entity Event using a property of the Organization entity. So basically when I fetch events, only return the events that have an Organization.code= :codeParam.
To accomplish that I implemented a hibernate filter with :
#FilterDef(name="codeFilter", parameters=#ParamDef( name="codeParam", type="string" ) )
...
#ManyToOne
#JoinColumn(name="Organization_Id")
#Filter(name="codeFilter", condition=" code = :codeParam")
private Organization organization;
...
Filter hibernateFilter = sess.enableFilter("codeFilter");
hibernateFilter.setParameter("codeParam", "hola");
Unfortunately according to a post from the Hibernate Team on the hibernate forums, this is not possible :
A Hibernate data filter does not change the multiplicity of an association. By definition it therefore does not filter many-to-one, one-to-one, or any load() or get() operation.
What is it supposed to do, return NULL instead of an instance? NULL does not mean FILTERED, it means NULL. You guys are using filters wrong.
So my question is : is there any way to filter the base entity ("Event") with a condition on the entity from a manyToOne relationship (Organization.code= :codeParam)?
I need this to be enforced every time there is a fetch of events, so a solution using the already existing hibernate filters or something similar would be greatly appreciated.
EDIT1: The question is a simple example of what needs to be done on a significantly bigger scale. Basically, we want to add security to all our Entities and their own nested Entities through the use of a globally defined filter on a Unix permissions row that all our tables have.
WARNING: Do not do this, it is dependent on Hibernate internals and prone to breaking on schema changes, and possibly on variations in individual query setup.
Set Hibernate to show its generated sql, run the query you want to filter (in this case, loading some Event objects), and check what name it assigns to the join used for fetching the related Organization. For example, the generated sql might include inner join Organization someNameHere on this_.Organization_Id = someNameHere.OrganizationId. Then apply the filter, not to the association, but to the Event class, with condition "someNameHere.code = :codeParam".
This is, unfortunately, the only way I've been able to find to filter one class by the properties of an associated class.
I'm trying to make a more robust solution, but it's a complex issue and I'm still in the research stage for that. I expect it will use code generation (through an annotation processor) and programmatic modification of Hibernate's mapping information on startup, but I'm not sure what else yet.

CascadeType vs FetchType

I would like to now what is the difference between CascadeType and FetchType in Hibernate?
They seem very similar but I guess they are not interchangeable, right?
When to use them? Can they be used both at the same time?
These are 2 different things:
The CascadeType in Hib. could be REFRESH, MERGE, ..., ALL you put it under the related entity and it determines the behavior of the related entity if the current entity is: refreshed, updated, deleted, e.t.c.. So whenever you entity is affected the CascadeType tells if the related entity should be affected as well.
The FetchType could be only of 2: EAGER and LAZY. This one you as well put under the related entity and it determines whether the related entity should be initialized right away when the current entity is initialized (EAGER) or only on demand (LAZY).
Cascading is used for propagating entity state transitions from a Parent entity to a Child.
Fetching is used for loading associated entities and you can have:
global fetch policies (defined through entity mapping)
query-time fetch policy (using the HQL/JPQL FETCH directive)
Both are different configurations, you can relate it with simple SQL.
Cascade tells you what happens when one entity gets updated ( on delete cascade in sql)
Fetch tells how the query is going to be executed ( join, lazy ...)
There's a big difference between the two of them.
CascadeType is a property used to define cascading in arelationship between a parent and a child.
FetchType is a property used to define fetching strategies which are used to optimize the Hibernate generated select statement, so that it
can be as efficient as possible.
You can find more about them in:
Hibernate – fetching strategies examples
Hibernate JPA Cascade Types

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.

Categories