Thursday, 26 July 2018

What is Lazy Loading in Hibernate? Explain with an Example

      In the previous post, we discussed the Hibernate JPA Cascade Types. In this post, we will discuss lazy loading in Hibernate.

What Is Lazy Loading in Hibernate?

Lazy loading determines whether child objects should be loaded when the parent object is retrieved from the database. In Hibernate XML mapping, you can configure this behavior using the lazy="true" attribute. When using annotations, you can specify the fetch strategy with FetchType.LAZY.

With lazy loading, child objects are not loaded immediately when the parent object is fetched. Instead, they are loaded only when they are accessed in the application. For example, when the getChild() method is called on the parent object, Hibernate executes an additional SQL query to retrieve the child objects.

In some scenarios, however, you may want the child objects to be loaded along with the parent object. In such cases, you can disable lazy loading by setting lazy="false" in the XML mapping or by using FetchType.EAGER with annotations. Hibernate will then fetch both the parent object and its associated child objects during the same retrieval process.

The default fetch type depends on the type of relationship:

  • @ManyToOne and @OneToOne have a default fetch type of FetchType.EAGER.

  • @OneToMany and @ManyToMany have a default fetch type of FetchType.LAZY.

Example:--

Employee.java
@Entity
@Table (name="employee")
public class Employee {
 
     @Id
     @Column(name="id")
     private int id;
 
     @Column(name="emp_name")
     private String name;
 
     @OneToMany(cascade=CascadeType.ALL, FetchType.LAZY) 
     @JoinColumn(name="address_id")
     private Set<Address> address;
       
        // setters and getters
}

            In the above example, Employee and Address entity have the One to Many relationship. The default fetch type of One to Many relationship is LAZY.

Address.java,


@Entity
@Table (name="address")
public class Address {
 
     @Id
     @Column(name="id")
     private int id;
 
     @Column(name="address")
     private String address;
       
        // setters and getters
}

Main Class,

HibernateMain.java,


package com.adnblog;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import com.adnblog.Employee;

public class HibernateMain {

      public static void main(String[] args) {

            SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
            Session session = sessionFactory.openSession();
            Transaction txn = session.beginTransaction();

            Employee emp = session.get(Employee.class, 1);   //check the below output
            System.out.println("Name:--"+emp.getName());
            Set<Address> addressSet = emp.getAddress();  
            tx.commit();                     
            sessionFactory.close();
      }
}

Output :--

select  employee0_.id as id1_0_0_, employee0_.name as name1_0_0_, employee0_.address as 
address2_0_0_  from Employee employee0_ where employee0_.id=?

Name:-- Kiran

select  employee0_.id as id1_0_0_,employee0_.name as name1_0_0_, employee1_.id as id2_0_0,  employee1_.address as 
address2_0_0_  from Employee employee0_  
join Address employee1_ where employee0_.id=?
         
         In the above example, Hibernate does not load the Address entity when the parent object is initially fetched. Instead, it returns a proxy object for the Address association. The Address table is queried only when the getAddress() method is invoked for the first time. At that point, Hibernate executes an additional SQL query to load the actual Address entity.

Hibernate does not support lazy initialization for detached objects. If you attempt to access a lazily loaded association after the Hibernate session has been closed, Hibernate throws a LazyInitializationException because it can no longer retrieve the required data from the database.

Summary

Choose the appropriate fetch strategy based on your application's requirements to avoid common Hibernate performance issues. In most cases, FetchType.LAZY is the recommended choice because it loads associated entities only when they are actually needed.

FetchType.EAGER instructs Hibernate to fetch the associated entities along with the parent entity during the initial query. This can be beneficial when the related entities are always required, as all the necessary data is retrieved in a single database query. However, in many scenarios, it introduces unnecessary overhead by loading entities that are never used, which can negatively impact application performance.

FetchType.LAZY delays the loading of associated entities until they are explicitly accessed in the application. This approach improves performance by avoiding unnecessary data retrieval. However, when a lazy association is accessed, Hibernate executes an additional SQL query to load the required data. Therefore, lazy loading should be used carefully to avoid performance issues such as the N+1 query problem.

By understanding the differences between FetchType.EAGER and FetchType.LAZY and using them appropriately, you can build Hibernate applications that are both efficient and scalable.

Thank you for visiting the blog!


Related Posts:--

Thursday, 19 July 2018

Hibernate JPA Cascade Types

            In previous post, we learned the Difference between save() and persist() method in Hibernate. In this, we can discuss Cascade Types in Hibernate.

          The Hibernate JPA Cascade types are as follows,
  • PERSIST  ->  CascadeType.PERSIST  - save() or persist() operations cascade to related entities.
  • MERGE ->  CascadeType.MERGE -  related entities are merged when the owning entity is merged.
  • REFRESH ->  CascadeType.REFRESH - It is the same thing for the refresh() operation.
  • REMOVE ->  CascadeType.REMOVE -  removes all related entities association with this setting when the owning entity is delete.
  • DETACH - > CascadeType.DETACH - It detaches all related entities if a “manual detach” occurs.
  • ALL - > CascadeType.ALL - It is shorthand for all of the above cascade operations.

CascadeType.PERSIST

        CascadeType.PERSIST cascades the persist operation to all associated entities.  If we persist data in one entity then data will be saved in associated entity also. 
         For example if the entity Employee is associated with Address, if we are trying to save the data of Employee then it will save both parent(Employee) and the child entity(Address).  In Hibernate we need to call persist() method to persist the entity.

Employee.java

@Entity
@Table (name="employee")
public class Employee {
 
    @Id
    @Column(name="id")
    private int id;
 
    @Column(name="emp_name")
    private String name;
 
    @OneToMany(cascade=CascadeType.PERSIST) 
    @JoinColumn( name="address_id")
    private Set<Address> address;


    // setters and getters
}

Address.java

@Entity
@Table(name="address")
public class Address {
 
    @Id
    @Column(name="id")
    private int id;
 
    @Column(name="address_type")
    private String type;
  
    @column( name="address")
    private String address;

       
    // setters and getters
}

Below is the main Hibernate class to persist or save the above entities,

Address address = new Address();
address.setType("Permanent");
address.setAddress("At-Post-Sonyal, Sangli");

Employee emp = new Employee();
emp.setName("Kiran");
emp.setAddress(address);

session.persist(emp);  // will save both employee and address entities

CascadeType.MERGE

        CascadeType.MERGE cascades the merge operation to all associated entities.  If we merge data in one entity then data will be update in associated entity also.

Example:-

Employee.java,
@Entity
@Table (name="employee")
public class Employee {
 
     @Id
     @Column(name="id")
     private int id;
 
     @Column(name="emp_name")
     private String name;
 
     @OneToMany(cascade=CascadeType.MERGE) 
     @JoinColumn( name="address_id")
     private Set<Address> address;
       
     // setters and getters
}

Address Entity is as same as above in the example.

The Hibernate main class to merge the entities as below code,


Address address = new Address();
address.setType("Permanent");
address.setAddress("At-Post-Sonyal, Sangli");

Employee emp = new Employee();
emp.setName("Kiran");
emp.setAddress(address);

session.merge(emp);

CascadeType.REFRESH

         CascadeType.REFRESH cascades the refresh operation to all associated entities refresh by hibernate session. If one entity is refreshed, other associated entities will also be refreshed if CascadeType.REFRESH is annotated.

Example:-

Employee.java
@Entity
@Table (name="employee")
public class Employee {
 
     @Id
     @Column(name="id")
     private int id;
 
     @Column(name="emp_name")
     private String name;
 
     @OneToMany(cascade=CascadeType.REFRESH) 
     @JoinColumn( name="address_id")
     private Set<Address> address;
       
        // setters and getters
}

Address Entity is as same as above in the example.

Example of session Refresh() method:--
Address address = new Address();
address.setType("Permanent");
address.setAddress("At-Post-Sonyal, Sangli");

Employee emp = getEmployeeDetails();// getting existing employee details
emp.setAddress(address);

session.refresh(emp);

//here it will refresh the address in both tables

CascadeType.REMOVE

             CascadeType.REMOVE cascades the remove operation of entity from hibernate session to all associated entities remove. If one entity is removed, other associated entities will also be removed.

Example:--

Employee.java
@Entity
@Table (name="employee")
public class Employee {
 
     @Id
     @Column(name="id")
     private int id;
 
     @Column(name="emp_name")
     private String name;
 
     @OneToMany(cascade=CascadeType.REMOVE) 
     @JoinColumn( name="address_id")
     private Set<Address> address;
       
        // setters and getters
}

Address Entity is as same as above in the example.

Example of session remove() method:--
Employee emp = getEmployeeDetails();// getting existing employee details

session.delete(emp);

//here it will delete data in both tables

CascadeType.DETACH

         CascadeType.DETACH cascades the detach operation to all associated entities detach  from hibernate session. If one entity is detached, other associated entities will also be detached.
         For example if the entity Employee is associated with Address and we are detaching entity, both the entities Employee and Address will be detached from current session of hibernate. In Hibernate we need to call detach() method to detach the entity. 

Example:--

Employee.java,
@Entity
@Table (name="employee")
public class Employee {
 
     @Id
     @Column(name="id")
     private int id;
 
     @Column(name="emp_name")
     private String name;
 
     @OneToMany(cascade=CascadeType.DETACH) 
     @JoinColumn( name="address_id")
     private Set<Address> address;
       
        // setters and getters
}

Address Entity is as same as above in the example.

Use detach() method of session in Hibernate to detach the entity.

CascadeType.ALL

           In Hibernate there are different cascading PERSIST, MERGE, REMOVE, REFRESH, DETACH. These cascading are called by methods persist(), merge(), delete(), refresh(), detach(). In case we want to cascade in all above situation, then we need to use CascadeType.ALL. If we annotate our property in an entity by CascadeType.ALL, then for every action, cascading will be achieved. 

Example:--

Employee.java,
@Entity
@Table (name="employee")
public class Employee {
 
     @Id
     @Column(name="id")
     private int id;
 
     @Column(name="emp_name")
     private String name;
 
     @OneToMany(cascade=CascadeType.ALL) 
     @JoinColumn( name="address_id")
     private Set<Address> address;
       
        // setters and getters
}


Thanks for visiting blog.

Sunday, 15 July 2018

Difference between save() and persist() method in Hibernate

           In previous post, we learned the difference between get() and load() methods in Hibernate. In this, we can discuss difference between the save() and persist() methods of Hibernate. This is one of the famous Hibernate interview question.

Difference between save() and persist() methods are as follows,

save and persist method in hibernate


save() method example:--


        The save() method which takes a transient object as input and put it to its persistent state. This method returns a generated identifier. 

package com.adnblog;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import com.adnblog.Employee;

public class HibernateSaveExample {

       public static void main(String[] args) {

             SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
             Session session = sessionFactory.openSession();
             Transaction txn = session.beginTransaction(); 

             Employee emp = new Employee();
             emp.setName("Mahesh");
             emp.setAddress("Sonyal");
  
             int id = (Integer) session.save(emp);   //save is called which will add this transient object to persistent state.
  
             txn.commit();                     
             sessionFactory.close();
      }
}


persist() method example:--


            In the same way persist() is another method to store objects in database i.e. changing transient objects to its persistent state. But persist() method does not return anything.

package com.adnblog;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import com.adnblog.Employee;

public class HibernatePersistentExample {

      public static void main(String[] args) {

            SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
            Session session = sessionFactory.openSession();
            Transaction txn = session.beginTransaction();

            Employee emp = new Employee();
            emp.setName("Mahesh");
            emp.setAddress("Sonyal");
  
            session.persist(emp);          //persist is called which will add this transient object to persistent state.
  
            tx.commit();                     
            sessionFactory.close();
      }
}

Thanks for visiting blog.....


Related Posts:--
1) What is the difference between get() and load() methods in Hibernate?
2) Hibernate Criteria Queries and Examples
3) Hibernate Query Language(HQL) Examples
4) What is a Hibernate Caching ? Explain first level and second level cache in Hibernate
5) What are different states of an entity bean in Hibernate?
6) Hibernate One to One Mapping Example - Annotation based
7) Hibernate - JPA Annotations with explanation
8) Advantages of Hibernate over JDBC

Saturday, 14 July 2018

Difference Between get() and load() Methods in Hibernate

          In the previous post, we learned about the Hibernate Criteria API with an example. In this post, we will discuss the difference between the get() and load() methods in Hibernate, which is one of the most commonly asked Hibernate interview questions.

        In Hibernate, the Session interface provides two methods for retrieving objects from the database: get() and load(). These methods are used in different situations, but both belong to the Session interface and are invoked as session.get() and session.load().

Session.load() method:


1) It will always return a proxy without hitting the database. In Hibernate, proxy is an object with   the given identifier value, its properties are not initialized yet, it just look like a temporary fake object.
2) load() method doesn’t hit the database.
3) If no row found , it will throws an ObjectNotFoundException.


Session.get() method:


1) It always hit the database and return the real object, an object that represent the database row, not proxy.
2) If no row found , it will returns null.
3) get() method always hit the database.
4) It returns real object not proxy.

get() method example:--


package com.adnblog;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import com.adnblog.HibernateUtil;

public class GetMethodHibernateExample {
    
     public static void main(String args[]) {
        
        //Create SessionFacctory
        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
        
        //Create Session from SessionFactory
        Session session = sessionFactory.openSession();
        
        //Begin the transaction
        session.beginTransaction();
        
        //Create Employee object
        Employee employee = (Employee) session.get(Employee.class,new Integer(4322));
        System.out.println("Employee Details:--");
        System.out.println("Employee Id   : "+employee.getId());
        System.out.println("Employee Name : "+employee.getName());
        System.out.println("Employee Age  : "+employee.getAge());
        System.out.println("Department    : "+employee.getDept());
        
        //Commit the changes
        session.getTransaction().commit();
        //Close the session
        session.close();
    }
}


Output : -

Hibernate: select employee0_.id as id1_0_0_, employee0_.AGE as AGE2_0_0_, 
employee0_.DEPT as DEPT3_0_0_, employee0_.NAME as NAME4_0_0_ from EMPLOYEE employee0_ 
where employee0_.id=?
Employee Details
Employee Id   : 4322
Employee Name : JIP
Employee Age  : 100
Department    : IT

       In the above code, we have used session.get() to retrieve the employee with the ID 4322, Hibernate immediately hits the database and returns the original Employee object. This is the reason, we are getting the below SQL query immediately when we retrieve the employee id (employee.getId()).

Hibernate: select employee0_.id as id1_0_0_, employee0_.AGE as AGE2_0_0_, 
employee0_.DEPT as DEPT3_0_0_, employee0_.NAME as NAME4_0_0_ from EMPLOYEE employee0_ 
where employee0_.id=?


load() method example:-


package com.adnblog;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import com.adnblog.HibernateUtil;

public class loadMethodHibernateExample {
    
     public static void main(String args[]) {
        
        //Create SessionFacctory
        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
        
        //Create Session from SessionFactory
        Session session = sessionFactory.openSession();
        
        //Begin the transaction
        session.beginTransaction();
        
        //Create Employee object
        Employee employee = (Employee) session.load(Employee.class,new Integer(4322));
        System.out.println("Employee Details:--");
        System.out.println("Employee Id   : "+employee.getId());
        System.out.println("Employee Name : "+employee.getName());
        System.out.println("Employee Age  : "+employee.getAge());
        System.out.println("Department    : "+employee.getDept());
        
        //Commit the changes
        session.getTransaction().commit();
        //Close the session
        session.close();
    }
}

Output :-
Employee Details:--
Employee Id   : 4322
Hibernate: select employee0_.id as id1_0_0_, employee0_.AGE as AGE2_0_0_, 
employee0_.DEPT as DEPT3_0_0_, employee0_.NAME as NAME4_0_0_ from EMPLOYEE employee0_
 where employee0_.id=?
Employee Name : JIP
Employee Age  : 100
Department    : IT

         In the above code, we have used session.load() to retrieve the employee with the ID 4322, Hibernate immediately created the fake Employee object with the Id 4322 and the remaining properties would not have been initialized.
         It will hit the database only when it tries to retrieve other properties of Employee object.



Related Posts:--
1)  Hibernate Criteria Queries and Examples
2) Hibernate Query Language(HQL) Examples
3) What is a Hibernate Caching ? Explain first level and second level cache in Hibernate
4) What are different states of an entity bean in Hibernate?
5) Hibernate One to One Mapping Example - Annotation based
6) Hibernate - JPA Annotations with explanation
7) Advantages of Hibernate over JDBC

Wednesday, 11 July 2018

Hibernate Criteria Queries with Examples

In the previous post, we learned about Hibernate Query Language (HQL) with examples. In this post, we will discuss the Hibernate Criteria API, its features, and its usage with examples.

Hibernate provides three ways to retrieve data from a database:

  1. Using the Session interface (get() and load() methods) – These methods provide limited control over data retrieval and are primarily used to fetch entities by their primary key.

  2. Using HQL (Hibernate Query Language) – HQL provides more flexibility by supporting WHERE, ORDER BY, GROUP BY, and other clauses. However, HQL queries can become difficult to read and maintain as they grow in complexity.

  3. Using the Criteria API – The Criteria API allows you to build queries programmatically, making them easier to construct, maintain, and modify dynamically.


What is Criteria API ?


          The Hibernate Criteria API provides an elegant way to build dynamic queries for retrieving data from a database.

The Criteria API is a simplified, object-oriented alternative to Hibernate Query Language (HQL). It allows you to construct queries programmatically instead of writing HQL strings, making it more flexible and easier to maintain when building dynamic queries with complex conditions.

The org.hibernate.Criteria interface defines the methods used to create and execute criteria queries. The Hibernate Session interface provides the createCriteria() method, which accepts either a persistent class or its entity name. Hibernate then creates a Criteria object that returns instances of the specified entity class when the query is executed.

Example:-

The following example demonstrates a simple Criteria API query without any restrictions or optional parameters. It retrieves all records from the corresponding entity table.

Criteria criteria = session.createCriteria(Employee.class);
List<Employee> results = criteria.list();

Next example, we will see some examples of Restrictions.

Using Restrictions with Criteria:-


            The Hibernate Criteria API makes it easy to add restrictions to queries and retrieve only the required objects. You can add restrictions to a Criteria object by using the add() method.

The add() method accepts an org.hibernate.criterion.Criterion object, which represents an individual query condition. A criteria query can contain one or more restrictions, allowing you to build complex queries by combining multiple conditions.

  • Restrictions.eq() Example
      To retrieve objects whose property value matches a specific value, use the eq() method provided by the Restrictions class, as shown below:

Criteria criteria= session.createCriteria(Employee.class);
criteria.add(Restrictions.eq("name","Anil"));
List<Employee> results = criteria.list();

It will fetch all employee's having name with Anil.

  •  Restrictions.ne() Example

        To retrieve objects whose property value is not equal to a specified value, use the ne() method of the Restrictions class, as shown below:

Criteria criteria= session.createCriteria(Employee.class);
criteria.add(Restrictions.ne("name","Anil"));
List<Employee> results = criteria.list()

It will fetch all employee's except name with Anil.

  •  Restrictions.like() and Restrictions.ilike() Example

          Using the like() and ilike() methods of the Restrictions class, you can retrieve objects whose property values match a specified pattern. These methods are similar to the SQL LIKE clause.

The like() method performs a case-sensitive comparison, whereas the ilike() method performs a case-insensitive comparison.

Criteria criteria= session.createCriteria(Employee.class);
criteria.add(Restrictions.like("name","Mahesh%",MatchMode.ANYWHERE));
List<Employee> results = criteria.list();

org.hibernate.criterion.MatchMode object to specify how to match the specified value to the stored data. The MatchMode object  has four different matches:

ANYWHERE: Anyplace in the string
END: The end of the string
EXACT: An exact match
START: The beginning of the string.


  • Restrictions.isNull() and Restrictions.isNotNull() Example

      The isNull() and isNotNull() method of Restrictions is to search the null and not null value of the property.

Criteria criteria= session.createCriteria(Employee.class);
criteria.add(Restrictions.isNull("name"));
List<Employee> results = criteria.list();

The isNotNull() is same like isNull() but it will return the property having not null values.


  •  Restrictions.gt(), Restrictions.ge(), Restrictions.lt() and Restrictions.le() Examples

          The Hibernate Criteria API provides several restriction methods for performing comparison operations. The gt() method is used for greater-than comparisons, ge() for greater-than-or-equal-to comparisons, lt() for less-than comparisons, and le() for less-than-or-equal-to comparisons.

Criteria crt= session.createCriteria(Employee.class);
crt.add(Restrictions.gt("age", 40));
List<Employee> results = crt.list();

Paging Through the ResultSet:--


        In SQL query, we can use Offset and limit for pagination but in Criteria API have methods setFirstResult(int arg) and setMaxResults(int arg). Using these two methods we can construct paging component in our application.

Criteria criteria = session.createCriteria(Employee.class);
criteria.setFirstResult(1);
criteria.setMaxResults(20);
List<Employee> results = criteria.list();

The above query paginate 20 records each page, you can change this to 10 or 5 by setting setMaxResults to 10 or 5.

Obtaining a Unique Result:--

            If you want to retrieve a single object instead of a List, you can use the uniqueResult() method of the Criteria object. This method returns a single object if exactly one result is found, or null if no matching record exists. If the query returns more than one result, uniqueResult() throws a HibernateException.

The following example demonstrates a query that would normally return multiple results. However, by using the setMaxResults() method, the result set is limited to a single record.

Criteria criteria = session.createCriteria(Employee.class);
Criterion age = Restrictions.gt("age", 40);
criteria.setMaxResults(1);
Employee employee = (Employee) criteria.uniqueResult();

Obtaining Distinct Results:--


        Hibernate Criteria provides a result transformer for distinct entities, 
org.hibernate.transform.DistinctRootEntityResultTransformer, which ensures that no duplicates will be in your query’s result set. Rather than using SELECT DISTINCT with SQL, the distinct result transformer compares each of your results using their default hashCode() methods, and only adds those results with unique hash codes to your result set.

Criteria criteria = session.createCriteria(Employee.class);
Criterion age = Restrictions.gt("age", 40);
criteria.setResultTransformer( DistinctRootEntityResultTransformer.INSTANCE )
List<Employee> results = criteria.list();

Sorting the Query’s Results using Order:--


        Sorting the query’s results works much the same way with criteria as it would with HQL or SQL. The Criteria API provides the org.hibernate.criterion.Order class to sort your result set in either ascending or descending order, according to one of your object’s properties.

The below example demonstrates how to use the Order in Criteria,

Criteria crt = session.createCriteria(Employee.class);
crt.add(Restrictions.gt("age", 30));
crt.addOrder(Order.desc("age"));
List<Employee> results = crt.list();