get and load persistence operations

Click here to download eclipse supported ZIP file



Often times, you will notice Hibernate developers mix use of session.get() and session load(), do you wonder what’s the different and when you should use either of it?

Different between session.get() and session.load()

Actually, both functions are use to retrieve an object with different mechanism, of course.

1. session.load()

  • It will always return a “proxy” (Hibernate term) 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.
  • If no row found , it will throws an ObjectNotFoundException.

2. session.get()

  • It always hit the database and return the real object, an object that represent the database row, not proxy.
  • If no row found , it return null.

It’s about performance

Hibernate create anything for some reasons, when you do the association, it’s normal to obtain retrieve an object (persistent instance) from database and assign it as a reference to another object, just to maintain the relationship. Let’s go through some examples to understand in what situation you should use session.load().

2. session.get()

  • It always hit the database and return the real object, an object that represent the database row, not proxy.
  • If no row found , it return null.

It’s about performance

Hibernate create anything for some reasons, when you do the association, it’s normal to obtain retrieve an object (persistent instance) from database and assign it as a reference to another object, just to maintain the relationship. Let’s go through some examples to understand in what situation you should use session.load().

1. session.get()

For example, in a Address application , Address and Students should have a “one-to-many” relationship, when you want to save a address transaction, it’s common to declared something like below

           
    	   Address address = (Address)session.get(Address.class, new Integer(2));
           Student student = new Student();
           //set student detail
           student.setAddress(address);        
           session.save(student);

Output


Hibernate: 
    select ... from cv.address address0_ 
    where address0_.STOCK_ID=?
Hibernate: 
    insert into cv.address_transaction (...) 
    values (?, ?, ?, ?, ?, ?)

In session.get(), Hibernate will hit the database to retrieve the Address object and put it as a reference to Student. However, this save process is extremely high demand, there may be thousand or million transactions per hour, do you think is this necessary to hit the database to retrieve the Address object everything save a address transaction record? After all you just need the Address’s Id as a reference to Student.

2. session.load()

In above scenario, session.load() will be your good solution, let’s see the example,

           
    	   Address address = (Address)session.load(Address.class, new Integer(2));
           Student student = new Student();
           //set student detail
           student.setAddress(address);        
           session.save(student);

Output


Hibernate: 
    insert into cv.address_transaction (...) 
    values (?, ?, ?, ?, ?, ?)

In session.load(), Hibernate will not hit the database (no select statement in output) to retrieve the Address object, it will return a Address proxy object – a fake object with given identify value. In this scenario, a proxy object is enough for to save a address transaction record.

Exception

In exception case, see the examples

session.load()


Address address = (Address)session.load(Address.class, new Integer(100)); //proxy

 //initialize proxy, no row for id 100, throw ObjectNotFoundException
System.out.println(address.getAddressCode());

It will always return a proxy object with the given identity value, even the identity value is not exists in database. However, when you try to initialize a proxy by retrieve it’s properties from database, it will hit the database with select statement. If no row is found, a ObjectNotFoundException will throw.


org.hibernate.ObjectNotFoundException: No row with the given identifier exists: 
[com.cv.common.Address#100]

session.get()


//return null if not found
Address address = (Address)session.get(Address.class, new Integer(100)); 
System.out.println(address.getAddressCode()); //java.lang.NullPointerException

It will always return null , if the identity value is not found in database.

Conclusion

There are no always correct solution, you have to understand the differential in between, and decide which method is best fix in your application.



Here is the example code to test get() and load() functionality :



This is hibernate.cfg.xml file for connecting the postgreSQL database.



 
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
   <!-- <session-factory> <property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property> 
		hibernate word is optional <property name="connection.url">jdbc:oracle:thin:@localhost:1521:ORCL</property> 
		<property name="hibernate.connection.username">kcv</property> <property name="hibernate.connection.password">kcv</property> 
		<property name="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</property> 
		<property name="show_sql">true</property> <mapping resource="Address.hbm.xml"/> 
		</session-factory> -->
   <session-factory>
      <property name="hibernate.current_session_context_class">thread</property>
      <property name="hbm2ddl.auto">create</property>
      <property name="dialect">org.hibernate.dialect.PostgreSQLDialect</property>
      <property name="connection.url">jdbc:postgresql://localhost:5432/hibernate</property>
      <property name="connection.username">postgres</property>
      <property name="connection.password">password</property>
      <property name="connection.driver_class">org.postgresql.Driver</property>
      <property name="show_sql">true</property>
      <property name="format_sql">true</property>
      <property name="use_sql_comments">true</property>
      		<mapping resource="AddressBean.hbm.xml" />
   </session-factory>
</hibernate-configuration>


This is AddressBean.hbm.xml mapping file for map the Entity(POJO) class to columns.



 
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.cv.hibernate.model.AddressBean"
table="EMPLOYEE_GETLOAD">
<id name="id" column="EID" type="java.lang.Long">
</id>
<property name="firstName" type="java.lang.String">
<column name="FIRSTNAME" length="29" not-null="true" />
</property>
<property name="lastName" type="java.lang.String">
<column name="LASTNAME" length="29" not-null="true" />
</property>
<property name="email" type="java.lang.String">
<column name="EMAIL" length="39" not-null="true" />
</property>
</class>
</hibernate-mapping>



This is Get.java main class having the application business logic.



 

    
package com.cv.hibernate;

import org.apache.log4j.Logger;
import org.hibernate.Session;

import com.cv.hibernate.model.AddressBean;
import com.cv.hibernate.util.HibernateUtil;
/** @author Chandra Vardhan */

public class Get {

  private final static Logger logger = Logger.getLogger(Get.class);

  public static void main(String args[]) throws Exception {
    Session session = HibernateUtil.getSession();

    // ses.beginTransaction();

    AddressBean eb = (AddressBeansession.get(AddressBean.class, new Integer(100));

    logger.info(eb.getId());
    logger.info(eb.getFirstName() " " + eb.getLastName() " " + eb.getEmail());

    // Integer io = (Integer) ses.save(eb);
    // ses.saveOrUpdate(eb);
    // logger.info("id value===" + io);

    // ses.getTransaction().commit();
    HibernateUtil.closeSession();
    
  }
}


This is Get_vs_Load.java main class having the application business logic.



 

    
package com.cv.hibernate;

import org.apache.log4j.Logger;
import org.hibernate.Session;

import com.cv.hibernate.model.AddressBean;
import com.cv.hibernate.util.HibernateUtil;

/**
 @author Chandra Vardhan
 */
public class Get_vs_Load {

  private final static Logger logger = Logger.getLogger(Get_vs_Load.class);

  public static void main(String args[]) throws Exception {
    HibernateUtil.saveOrUpdate();
    Session session = HibernateUtil.getSession();
    AddressBean get1 = (AddressBeansession.get(AddressBean.class,
        new Long(101));
    logger.info("AddressBean get called");
    logger.info("AddressBean ID= " + get1.getId());

    AddressBean get2 = (AddressBeansession.get(AddressBean.class,
        new Long(102));
    logger.info("AddressBean get called");
    logger.info("AddressBean ID= " + get2.getId());
    logger.info("AddressBean ID= " + get2.getLastName());

    // load Example
    AddressBean load1 = (AddressBeansession.load(AddressBean.class,
        new Long(103));
    logger.info("AddressBean load called");
    logger.info("AddressBean ID= " + load1.getId());

    AddressBean load2 = (AddressBeansession.get(AddressBean.class,
        new Long(104));
    logger.info("AddressBean get called");
    logger.info("AddressBean ID= " + load2.getId());
    HibernateUtil.closeSession();

  }
}


This is Load.java main class having the application business logic.



 

    
package com.cv.hibernate;

import org.apache.log4j.Logger;
import org.hibernate.Session;

import com.cv.hibernate.model.AddressBean;
import com.cv.hibernate.util.HibernateUtil;

/**
 @author Chandra Vardhan
 */
public class Load {

  private final static Logger logger = Logger.getLogger(Load.class);

  public static void main(String args[]) throws Exception {
    Session session = HibernateUtil.getSession();

    session.beginTransaction();

    AddressBean eb = new AddressBean();

    session.load(eb, new Integer(101));

    logger.info(eb.getId() " " + eb.getFirstName() " " + eb.getLastName() " " + eb.getEmail());

    AddressBean eb2 = (AddressBeansession.load(AddressBean.class, new Integer(100));

    logger.info(eb2.getId());

    logger.info(eb2.getId() " " + eb2.getFirstName() " " + eb2.getLastName() " " + eb2.getEmail());
    session.getTransaction().commit();
    HibernateUtil.closeSession();
    
  }
}


This is AddressBean.java Entity(POJO) class having the fields needs to be configured in mapping file.



 

    
package com.cv.hibernate.model;

/**
 @author Chandra Vardhan
 */
public class AddressBean {
  private long id;
  private String firstName;
  private String lastName;
  private String email;

  public long getId() {
    return id;
  }

  public void setId(long id) {
    this.id = id;
  }

  public String getFirstName() {
    return firstName;
  }

  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }

  public String getLastName() {
    return lastName;
  }

  public void setLastName(String lastName) {
    this.lastName = lastName;
  }

  public String getEmail() {
    return email;
  }

  public void setEmail(String email) {
    this.email = email;
  }

}


This is HibernateUtil.java utility class for getting the database connection.



 

    
package com.cv.hibernate.util;

import org.apache.log4j.Logger;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;

import com.cv.hibernate.model.AddressBean;

/**
 @author Chandra Vardhan
 */
/**
 * Configures and provides access to Hibernate sessions, tied to the current
 * thread of execution. Follows the Thread Local Session pattern, see
 {@link http://hibernate.org/42.html }.
 */
public class HibernateUtil {
  private final static Logger logger = Logger.getLogger(HibernateUtil.class);

  /**
   * Location of hibernate.cfg.xml file. Location should be on the classpath
   * as Hibernate uses #resourceAsStream style lookup for its configuration
   * file. The default classpath location of the hibernate config file is in
   * the default package. Use #setConfigFile() to update the location of the
   * configuration file for the current session.
   */
  private static String CONFIG_FILE_LOCATION = "hibernate.cfg.xml";
  private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
  private static Configuration configuration = new Configuration();
  private static SessionFactory sessionFactory;

  static {
    try {
      configuration = configuration.configure(CONFIG_FILE_LOCATION);
      StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder()
          .applySettings(configuration.getProperties());
      sessionFactory = configuration.buildSessionFactory(builder.build());
      logger.info("%%%% Connection successful %%%%");
    catch (Exception e) {
      logger.error("%%%% Error Creating SessionFactory %%%%");
      e.printStackTrace();
    }
  }

  private HibernateUtil() {
  }

  /**
   * Returns the ThreadLocal Session instance. Lazy initialize the
   <code>SessionFactory</code> if needed.
   
   @return Session
   @throws HibernateException
   */
  public static Session getSession() throws HibernateException {
    Session session = (SessionthreadLocal.get();

    if (session == null || !session.isOpen()) {
      if (sessionFactory == null) {
        rebuildSessionFactory();
      }
      session = (sessionFactory != null? sessionFactory.openSession()
          null;
      threadLocal.set(session);
    }

    return session;
  }

  /**
   * Rebuild hibernate session factory
   
   */
  public static void rebuildSessionFactory() {
    try {
      configuration = configuration.configure(CONFIG_FILE_LOCATION);
      StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder()
          .applySettings(configuration.getProperties());
      sessionFactory = configuration.buildSessionFactory(builder.build());
      logger.info("%%%% Connection successful %%%%");
    catch (Exception e) {
      logger.error("%%%% Error Creating SessionFactory %%%%");
      e.printStackTrace();
    }
  }

  /**
   * Close the single hibernate session instance.
   
   @throws HibernateException
   */
  public static void closeSession() throws HibernateException {
    Session session = (SessionthreadLocal.get();
    threadLocal.set(null);

    if (session != null) {
      session.close();
      System.exit(0);
    }
  }

  /**
   * return session factory
   
   */
  public static SessionFactory getSessionFactory() {
    return sessionFactory;
  }

  /**
   * return hibernate configuration
   
   */
  public static Configuration getConfiguration() {
    return configuration;
  }

  public static void saveOrUpdate() {
    Session session = getSession();
    for (int i = 101; i < 106; i++) {
      AddressBean eb = new AddressBean();
      eb.setId(new Long(i));
      eb.setFirstName("chandra");
      eb.setLastName("vardhan");
      eb.setEmail("meetkodam@gmail.com");
      session.beginTransaction();
      session.saveOrUpdate(eb);
      session.getTransaction().commit();
    }
    session.close();
    logger.info("Saved successful...");

  }
}


This is log4j.properties file having the entries for logging the information into the console/file.




#By default enabling Console appender
# Root logger option
log4j.rootLogger=INFO, stdout

# Redirect log messages to console
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%-5p [%c]:%L -->> %m%n

# Redirect log messages to a log file
#log4j.appender.file=org.apache.log4j.RollingFileAppender
#log4j.appender.file.File=C:\\servlet-application.log
#log4j.appender.file.MaxFileSize=5MB
#log4j.appender.file.MaxBackupIndex=10
#log4j.appender.file.layout=org.apache.log4j.PatternLayout
#log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n


This is pom.xml file having the entries of dependency jars and information to build the application .



	
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.cv.hb</groupId> <artifactId>All_operations</artifactId> <version>1.0</version> <dependencies> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>4.3.5.Final</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-c3p0</artifactId> <version>4.3.5.Final</version> </dependency> <dependency> <artifactId>hibernate-core</artifactId> <groupId>org.hibernate</groupId> <version>4.3.5.Final</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>4.2.0.Final</version> </dependency> <dependency> <groupId>org.hibernate.common</groupId> <artifactId>hibernate-commons-annotations</artifactId> <version>4.0.4.Final</version> </dependency> <dependency> <groupId>org.hibernate.javax.persistence</groupId> <artifactId>hibernate-jpa-2.0-api</artifactId> <version>1.0.1.Final</version> </dependency> <dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>1.0.0.GA</version> provided </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.6.4</version> </dependency> <dependency> <groupId>org.jboss.logging</groupId> <artifactId>jboss-logging</artifactId> <version>3.1.0.CR2</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.6.4</version> </dependency> <dependency> <groupId>postgresql</groupId> <artifactId>postgresql</artifactId> <version>9.1-901.jdbc4</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>1.7.5</version> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.3</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project>

No comments:

Post a Comment