Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does JPA use FetchType EAGER by default for the @ManyToOne relationship

I came to notice that the default FetchType for the @ManyToOne mapping is EAGER in JPA and Hibernate, whereas for the @OneToMany mapping, the default FetchType is LAZY.

What is the specific reason behind this?

like image 635
vatsal mevada Avatar asked Dec 17 '14 06:12

vatsal mevada


2 Answers

From the JPA 2.0 spec, the defaults are like so:

OneToMany: LAZY
ManyToOne: EAGER
ManyToMany: LAZY
OneToOne: EAGER

And in hibernate, all is Lazy

From Hibernate Docs,

By default, Hibernate uses lazy select fetching for collections and lazy proxy fetching for single-valued associations. These defaults make sense for most associations in the majority of applications.

To answer your question, Hibernate is an implementation of the JPA standard. Hibernate has its own quirks of operation, but as per the Hibernate docs

By default, Hibernate uses lazy select fetching for collections and lazy proxy fetching for single-valued associations. These defaults make sense for most associations in the majority of applications.

So Hibernate will always load any object using a lazy fetching strategy, no matter what type of relationship you have declared.

JPA Spec assumes that in general most of the applications will require the singleton relations by default be eager, whereas multi value relations by default be lazy.

Refer here for more

like image 118
Ankur Singhal Avatar answered Sep 29 '22 20:09

Ankur Singhal


JPA gotcha

The reason for setting those to EAGER was because the early JPA 1.0 designers assumed that enforcing JPA implementations to support dynamically initializing Proxies would be a very strong requirement. However, since without Proxies, performance would suffer tremendously, all providers support LAZY associations.

Avoid FetchType.EAGER

Using the default EAGER fetching strategy for @ManyToOne and @OneToOne associations is a terrible idea as you can easily end up with N+1 query issues.

When using Hibernate, once an association is set to FetchType.EAGER, you can no longer fetch it lazily at query time. So, you are always going to fetch that relationship whether the current business use case needs it or not.

Use FetchType.LAZY by default

So, you are better off using FetchType.LAZY by default for all associations.

Unlike FetchType.EAGER, a FetchType.LAZY relationship can be fetched eagerly at query time using a JOIN FETCH clause.

The only thing you need to be aware of is that you need to fetch a lazy association in the context of the currently running Persistence Context if you need to access the association after the JPA EntityManager is closed. Otherwise, you are going to get a LazyInitializationException

like image 22
Vlad Mihalcea Avatar answered Sep 29 '22 20:09

Vlad Mihalcea