Reputation: 51
Multiple Entities are associated with @OnetoMany relations and Eager Loaded with an Entity. While fetching data using Hibernate criteria, the related Eager column is initialized which is causing performance issue for my project as it is huge and there are many Eager loaded relationships.
What would be the best way to avoid initialization of Eager column while using hibernate criteria to fetch data.
Upvotes: 4
Views: 3309
Reputation: 790
You can explicitly define properties with criteria to be fetched in lazy mode.
criteria.setFetchMode("property_name", FetchMode.SELECT);
In hibernate code SELECT is Lazy.
public static final FetchMode LAZY = SELECT;
Hibernate document link
Upvotes: 0
Reputation: 1630
You could use a projection. If you are using Spring Data, it includes some nice helpers see Baeldung: Spring Data JPA Projections and Spring Data JPA Reference for details. If you are using Hibernate directly, see Baeldung: JPA/Hibernate Projection and Hibernate JavaDoc Projection
Hibernate (direct quote from Baeldung)
To project on multiple columns using JPQL, we only have to add all the required columns to the select clause:
Query query = session.createQuery("select id, name, unitPrice from Product"); List resultList = query.getResultList();
But, when using a CriteriaBuilder, we'll have to do things a bit differently:
CriteriaBuilder builder = session.getCriteriaBuilder(); CriteriaQuery<Object[]> query = builder.createQuery(Object[].class); Root product = query.from(Product.class); query.multiselect(product.get("id"), product.get("name"), product.get("unitPrice")); List<Object[]> resultList = entityManager.createQuery(query).getResultList();
Here, we've used the method multiselect() instead of select(). Using this method, we can specify multiple items to be selected.Another significant change is the use of Object[]. When we select multiple items, the query returns an object array with value for each item projected. This is the case with JPQL as well.
Let's see what the data looks like when we print it:
[1, Product Name 1, 1.40] [2, Product Name 2, 4.30] [3, Product Name 3, 14.00] [4, Product Name 4, 3.90] As we can see, the returned data is a bit cumbersome to process. But, fortunately, we can get JPA to populate this data into a custom class.
Also, we can use CriteriaBuilder.tuple() or CriteriaBuilder.construct() to get the results as a list of Tuple objects or objects of a custom class respectively.
I suggest reading the Baeldung article, it goes into more detail.
Upvotes: 1
Reputation: 36
Which JPA version are you using?
JPA 2.1 has introduced Dynamic fetching via JPA entity graph
Or you may probably try with Dynamic fetching via Hibernate profile
Refer https://docs.jboss.org/hibernate/orm/5.1/userguide/html_single/chapters/fetching/Fetching
https://docs.jboss.org/hibernate/orm/5.0/userguide/en-US/html/ch09.html
Upvotes: 0
Reputation: 564
I would suggest using fetch= FetchType.LAZY but you have to check code for transactions. If they are created then you're fine, otherwise you'll get LazyInitializationException when trying to use that data.
If you don't want it to be eagerly fetched every time you fetch parent entities there is two solutions without changing legacy code. First one is to create entity graph and including that in graph. So you would fetch data with your graph and that would be it. No more additional sql queries to fetch eager collection. Second solution is to create entity for same table but with everything marked lazy.
Upvotes: 0
Reputation: 11
I would also suggest the same that has been mentioned by Mayuree. In further, see if you can play below condition:
Upvotes: 0
Reputation: 130
If you are using @OneToMany annotation then there is an attribute called fetch= FetchType.LAZY.
You can use it. It will notify hibernate for Lazy loading. For more info you can refer Baeldung.com and search for Eager and Lazy Loading
Upvotes: 0