Thursday, 26 July 2018

What is lazy loading in Hibernate? Explain with an example

      In previous post, discussed the Hibernate JPA Cascade Types. In this post we can discuss the 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, the 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, by calling the getChild() method on the parent object. At that point, 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 and its associated child objects in the same retrieval process.

The default fetch type depends on the type of the 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 efficient when the related entities are always required, as all the necessary data is retrieved in a single database query. However, in many scenarios, it results in unnecessary overhead by loading entities that are not 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, it is important to use lazy loading carefully to avoid issues such as the N+1 query problem.

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

What is the 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 and Examples

               In previous post, we learned the  Hibernate Query Language(HQL) Examples.  In this post, we will discuss about the Criteria API of hibernate & it's usage with examples.

There are three way to fetch the data from the database in the Hibernate.
  • Using Session Interface - get() and load() methods  -limited control to accessing data
  • Using HQL(Hibernate Query Language) – Slightly more control using where clause and other clauses but it is more complicated to maintain in case of bigger queries with lots of clauses.
  • Using Criteria API

What is Criteria API ?


          The API (Application Programming Interface) of Hibernate Criteria provides an elegant way
 of building dynamic query on the persistence database.

          The hibernate criteria API is very Simplified API for fetching data from Criterion objects. The criteria API is an alternative of HQL (Hibernate Query Language) queries.  It is more powerful and flexible for writing tricky criteria functions and dynamic queries.

         The Criteria API allows you to build up a criteria query object programmatically.  The org.hibernate.Criteria interface defines the available methods for one of these objects. The Hibernate Session interface contains several createCriteria() methods.  Pass the persistent object’s class or its entity name to the createCriteria() method and Hibernate will create a Criteria object that returns instances of the persistence object’s class when your application executes a criteria query.

Examples:-


          The below is the simple example of Criteria API with no any restrictions or no any optional parameters, it will return the all the data of that entity class.            

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 Criteria API makes it easy to use restrictions in your queries to selectively retrieve objects. You can add restrictions to a Criteria object with the add() method. The add() method takes an org.hibernate.criterion.Criterion object that represents an individual restriction. You can have more than one restriction for a criteria query.

  • Restrictions.eq() Example
       To retrieve objects that have a property value that “equals” your restriction, use the eq() method on Restrictions, as follows:

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 that have a property value “not equal to” your restriction, use the ne() method on Restrictions, as follows:

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 like() and ilike() method of Restrictions, we can retrieve all objects that have a property matching part of a given pattern. It's kind of like and ilike clause of SQL. The ilike() method is case-insensitive.

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

          Several of the restrictions are useful for doing math comparisons. The greater-than comparison is gt(), the greater-than-or-equal-to comparison is ge(), the less-than comparison is lt(), and the less-than-or-equal-to comparison is le().

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 obtain a single Object reference instead of a List, the uniqueResult() method on the Criteria object returns an object or null. If there is more than one result, the uniqueResult() method throws a HibernateException.

        The following example demonstrates having a result set that would have included more than one result, except that it was limited with the setMaxResults() method,

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();