<img alt="" src="https://secure.leadforensics.com/150446.png " style="display:none;">
Go to top icon

Hibernate Performance Optimization (Part - 1)

Neetesh Kadam Jul 31, 2012

hibernate session.get Hibernate Performance Optimization Tuning Hibernate session.load Hibernate Proxy Pattern Technology

To work effectively with hibernate you need to understand how hibernate executes queries. You can get the work done by using various alternative APIs which hibernate provides, but selection of correct API is needed for performance optimization. In this post I will try to explain about how hibernate uses proxy design pattern to lazy load entities and how to effectively use it for performance optimization.

About Proxy Pattern:

Proxy pattern is used when you do not want to expose the actual object, the reason can be

  1. You want to hide the complexities of actual object. For example if the under laying object is handling data over network then you may want to create proxy object which will handle network related issues gracefully.
  2. Creation of actual object is expensive. Creation of actual object is postponed till it is really required; meanwhile the work can be done by simple proxy object.

How hibernate uses proxy pattern:

Hibernate uses proxy pattern to lazy load entities. For lazy loaded entity or collection, hibernate defers database hit till any property other than identifier (Property marked with @Id) is accessed. The proxy object which hibernate creates has only identifier value set. If it is collection then all item in collection has id set, no other properties are initialized.

Hibernate provides 2 different methods - get and load. Both methods use different fetching strategies. Load method uses lazy fetching whereas get method uses eager fetching.

So for example when you load the employee object in session like

Employee emp = session.load(Employee.class, 123L);

No database query is executed. Hibernate just create a placeholder object or proxy object which mocks Employee and returns that proxy object.

Now when you try to access the properties of Employee in persistent context like

emp.getName()

Then this is the first time hibernate will fire the select query which will load all properties of employee object. If above code is executed outside persistent context then Lazy initialization exception is thrown.

Consider the example of get

Employee emp = session.get(Employee.class, 123L);

This will immediately executes select statement and load all properties of employee object.

Behavior when employee with ID 123L exists in database.

Operation Load Get
session.load/get Returns proxy obhect(no select query is fired) Select query is fired. Returns fully loaded object
emp.getId() No query is executed for identifier getter method provided you define method level annotation like
@Id@GeneratedValue
public Integer getId() {
return id;
}
For Field level annotation it will fire select query.
@Id@GeneratedValue
private Integer id;
Doesn't matter, as object is already loaded
emp.getName() Select query is fired. As the object is already loaded, no database operation happens during this call.

Behavior when employee with ID 123L doesn't exists in database.

Operation Load Get
session.load/get No Exception is thrown null is returned
emp.getName() Exception is thrown
(No row with the given identifier exists)

How to improve performance using get and load.

Use case: Suppose you have department object and you just want to add employee to the department. So you will say

Employee emp = session.load(Employee.class, 1L);
dept.add(emp);
session.update(dept);

So if instead of load if you use get, then select query for employee will be fired which is really not required. In this way just by selecting load over get database hit can be reduced.

Conclusion: Using proxy object avoids unnecessary database hit. Use Load if you want to use proxy or use get if you don’t want proxy.

Note: Hibernate allows disabling proxy generation at class level by specifying @Proxy(lazy=false). If this annotation is used then no proxy is generated when loading the entity of this class. (In other words session.load(…) will also fire select query)

Collections which are initialized lazily also behave similar to the load method. For Lazy collection hibernate creates proxy which has only identifier values. This lazy collection is initialized as and when elements in collection are accessed based on fetch strategy (select fetch, subselect fetch, join fetch, batch fetch). Selecting appropriate fetch strategy also matters a lot from performance perspective. We will discuss this in next article.

e-Zest is a leading digital innovation partner for enterprises and technology companies that utilizes emerging technologies for creating engaging customers experiences. Being a customer-focused and technology-driven company, it always helps clients in crafting holistic business value for their software development efforts. It offers software development and consulting services for cloud computing, enterprise mobility, big data and analytics, user experience and digital commerce.