Wednesday, December 4, 2013

Why is Fetch(join) is not working with HQL?

@Fetch(JOIN) will be ignored if you use the Query interface (e.g.: session.createQuery()) but it will be properly used if you use the Criteria interface.

This is practically a bug in Hibernate which was never resolved. It is unfortunate because a lot of applications use the Query interface and cannot be migrated easily to the Criteria interface.

If you use the Query interface you always have to add JOIN FETCH statements into the HQL manually.

Hibernate Fetch plan and Fetch Strategies

The Hibernate Relations Works with different Fetch Strategies..!!

Hibernate provides 4 strategies for retrieving data:

SELECT

  @OneToMany(mappedBy="tableName", cascade=CascadeType.ALL)  @Column(name="id")   @Fetch(FetchMode.SELECT)

In this Method there are Multiple SQLs fired. This first one is fired for retrieving all the records in the Parent table. The remaining are fired for retrieving records for each Parent Record. This is basically the N+1 problem. The first query retrieves N records from database, in this case N Parent records. For each Parent a new query retrieves Child. Therefore for N Parent, N queries retrieve information from Child table.

JOIN

  @OneToMany(mappedBy="tableName", cascade=CascadeType.ALL)  @Column(name="id")  @Fetch(FetchMode.JOIN) 

This is similar to the SELECT fetch strategy except that fact that all database retrieval take place upfront in JOIN fetch unlike in SELECT where it happens on a need basis. This can become an important performance consideration.

SUBSELECT

   @OneToMany(mappedBy="tableName", cascade=CascadeType.ALL)   @Column(name="id")   @Fetch(FetchMode.SUBSELECT)

Two SQLs are fired. One to retrieve all Parent and the second uses a SUBSELECT query in the WHERE clause to retrieve all child that has matching parent ids.

BATCH

  @OneToMany(mappedBy="tableName", cascade=CascadeType.ALL)  @Column(name="id")  @@BatchSize(size=2)

The batch size maps to the number of Parent whose child are retrieved. So we can specify the number of records to be fetched at a time.But Multiple queries will be executed.!!

one-to-many & many-to-many allows - join, Select and SubSelect

many-to-one & one-to-one allows - Join and Select


Hibernate also distinguishes between (when is the associations are fetched)

1.Immediate fetching -

an association, collection or attribute is fetched immediately, when the Parent is loaded. (lazy="false")

2.Lazy collection fetching -

a collection is fetched when the application invokes an operation upon that collection. (This is the default for collections.(lazy="true")

3."Extra-lazy" collection fetching -

individual elements of the collection are accessed from the database as needed. Hibernate tries not to fetch the whole collection into memory unless absolutely needed (suitable for very large collections) (lazy="extra")

4.Proxy fetching -

a single-valued association is fetched when a method other than the identifier getter is invoked upon the associated object. (lazy="proxy")

5."No-proxy" fetching -

a single-valued association is fetched when the instance variable is accessed. Compared to proxy fetching, this approach is less lazy.(lazy="no-proxy")

6.Lazy attribute fetching -

an attribute or single valued association is fetched when the instance variable is accessed. (lazy="true")

one-to-many & many-to-many allows Immediate, Layzy, Extra Lazy

many-to-one & one-to-one allows Immediate Proxy, No Proxy

Google+