Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate: Overriding mapping's EAGER in HQL?

It's possible to override LAZY in HQL using LEFT JOIN FETCH.

FROM Obj AS obj LEFT JOIN FETCH obj.otherObj WHERE obj.id = :id

Is it also possible to override EAGER? How?

like image 700
Ondra Žižka Avatar asked Jun 18 '10 19:06

Ondra Žižka


People also ask

How can we avoid eager fetch in Hibernate?

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.

Which of the following fetching strategies can be used to support data access optimization in Hibernate?

fetch=”select” or @Fetch(FetchMode. This is the default fetching strategy. it enabled the lazy loading of all it's related collections. Let see the example… Hibernate: select ...from mkyong.stock where stock0_.


2 Answers

I had a situation that for historical reasons did eager fetch between several one-to-many dependencies. Over years many places came to depend on it so it was hard to turn off. However for some cases, the eager fetch was hindering: for every larger selection on the table, it would spawn 100s of small subqueries for each of the collections of each of the objects. I found a way to get around this, not really overriding the eager fetch, but for me just as useful: simply create a single query that does all the subfetches at once. This will make 1 physical query to the database, instead of having hibernate walk the dependency graph and spawn 100s of queries.

So I replaced

Query q = session.createQuery("from Customer c");

by

Query q = session.createQuery("from Customer c " +
                              "left join fetch c.vats v " +
                              "left join fetch v.klMemos bk " +
                              "left join fetch bk.ferryKlMemos");

1 Customer has many VAT numbers, 1 VAT number has many klmemos and so on. The old situation would first fetch only the customers and hibernate would then start fetching each of the dependent collections one by one. The second form will load everything in one native query, and hibernate will find all it needs to populate the eager collections in the object cache.

Note this approach also simulates fast eager fetch for collections that are configured to be lazy, as you're populating all the "lazy" collections in an eager (and efficient) way.

like image 71
geert3 Avatar answered Sep 29 '22 12:09

geert3


The qualifier in this snippet from the Hibernate Docs implies that you can override lazy with eager, but not the other way around:

If you are using property-level lazy fetching (with bytecode instrumentation), it is possible to force Hibernate to fetch the lazy properties in the first query immediately using fetch all properties.

Unusually, it looks like you can if you use the Criteria API to go from eager to lazy. Just call setFetchMode(FetchMode.LAZY) on the relevant join.

like image 29
sblundy Avatar answered Sep 29 '22 13:09

sblundy