Entities in a domain model are often related to each other. JPA 2.0 provides the following four annotations to define the relationships between entities:
- @OneToOne
- @OneToMany
- @ManyToOne
- @ManyToMany
The default fetch type of @OneToOne and @ManyToOne is EAGER fetch which means that while loading an entity the related entities would also get loaded whereas the default fetch type of @OneToMany and @ManyToMany is LAZY fetch.
I have often noticed that developers use EAGER fetch for all the four relationships mentioned above to avoid getting LazyInitializationException.
In complex domain model where there are multiple entities related to each other, using EAGER fetch would pull many objects while trying to retrieve an entity. Following are the drawbacks of using EAGER fetch in all associations:
- A whole object graph would be pulled in memory and it could lead to performance degradation. You may use all the related objects. So the best strategy is to fetch only the properties which are required. The related entities which are not needed should be lazily loaded.
- Hibernate uses joins on all the related entities loaded using EAGER fetch. When you work on a complex object graph, the number of joins in Select query generated by Hibernate could exceed 256. SQL Server 2008 has a restriction on the number of joins used. They cannot exceed 256.
- Hibernate gives multiple bag fetch exception when properties of type List with EAGER fetch are used. When you have a complex domain model with many entities eagerly fetched, it becomes difficult to track down the List which causes such an exception.
- Often, the complexity of the domain model in terms of the number of entities and their relationships with each other go on increasing as the application matures. When you start with a small domain model, using EAGER relationships may not make a significant impact. However, when the domain model grows, it could become difficult to tackle the problems mentioned before.
Due to the drawbacks mentioned above, I recommend using the default fetch types of the JPA annotations. Use EAGER fetch type for collections only when it is absolutely necessary. It is also a good practice to identify and monitor the performance of complex queries. Performance tuning of such queries can be carried out by implementing second level cache in Hibernate with the help of caching frameworks such as Ehcache.