Friday, December 27, 2013

Difference between openSession() and getCurrentSession()


In hibernate, there are two ways to get the org.hibernate.Session object.
  1. Using openSession() method
  2. Using getCurrentSession() method
1. openSession():

Session openSession() throws HibernateException

It will return a new session object on every call, which is actually a instance of org.hibernate.impl.SessionImpl.


private SessionImpl openSession(
Connection connection,
boolean autoClose,
long timestamp,
Interceptor sessionLocalInterceptor
) {
return new SessionImpl(
connection,
this,
autoClose,
timestamp,
sessionLocalInterceptor == null ? interceptor : sessionLocalInterceptor,
settings.getDefaultEntityMode(),
settings.isFlushBeforeCompletionEnabled(),
settings.isAutoCloseSessionEnabled(),
settings.getConnectionReleaseMode()
);
}

  • We can use this method when we decided to manage the Session our self.
  • It does not try to store or pull the session from the current context.
  • If we use this method, we need to flush() and close() the session. It does not flush and close() automatically.
Example:   


 Transaction transaction = null;
Session session = HibernateUtil.getSessionFactory().openSession();
try {
transaction = session.beginTransaction();
// do Some work

session.flush(); // extra work
transaction.commit();
} catch(Exception ex) {
if(transaction != null) {
transaction.rollback();
}
ex.printStackTrace();
} finally {
if(session != null) {
session.close(); // extra work
}
}

2. getCurrentSession():


Session getCurrentSession() throws HibernateException

Obtains the current session. The "current session" refers to a Hibernate Session bound by Hibernate behind the scenes, to the transaction scope.

A session is opened whenever getCurrentSession() is called for the first time and closed when the transaction ends. This creates a brand new session if one does not exist or uses an existing one if one already exists. It automatically configured with both auto-flush and auto-close attributes as true means Session will be automatically flushed and closed.

We can use getCurrentSession() method when our transaction runs long time. To use this method we need to configure one property in hibernate.cfg.xml file. The property is

<property name="hibernate.current_session_context_class">thread</property>

Values for the current_session_context_class will be,
  1. thread(local transaction)
  2. managed
  3. jta(global transaction)
1. thread - session bound to a thread, for single thread execution if you call a getCurrentSession() then it will return you a same session object.

2. managed - this provided for managing session from some external entity, something like intercepter. maintaining session in a ThreadLocal same as a "thread" type, but having a different methods like bind(), unbind(), hasbind() to be used by external entity to maintain session in a context.

3. jta - session will be bound to a transaction, as we says a transaction then we need application server for using this context class.

public org.hibernate.classic.Session getCurrentSession() throws HibernateException {
if ( currentSessionContext == null ) {
throw new HibernateException( "No CurrentSessionContext configured!" );
}
return currentSessionContext.currentSession();
}

Example:


        Transaction transaction = null;
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
try {
transaction = session.beginTransaction();
// do Some work

// session.flush(); // no need
transaction.commit();
} catch(Exception ex) {
if(transaction != null) {
transaction.rollback();
}
ex.printStackTrace();
} finally {
if(session != null) {
// session.close(); // no need
}
}

Main Example: 

hibernate.cfg.xml


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">


<hibernate-configuration>
<session-factory>
<property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="connection.password">ranga</property>
<property name="connection.url">jdbc:oracle:thin:@localhost:1521:xe</property>
<property name="connection.username">ranga</property>
<property name="dialect">org.hibernate.dialect.Oracle10gDialect</property>
<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>
<property name="show_sql">true</property>
<property name="hbm2ddl.auto">create</property>
<!-- <mapping resource="Order.hbm.xml"></mapping> -->
</session-factory>
</hibernate-configuration>

HibernateUtil.java


package com.ranga.util;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;

public class HibernateUtil {
private static SessionFactory sessionFactory = null;

static {
Configuration config = new Configuration();
config.configure();
ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
.applySettings(config.getProperties()).build();
sessionFactory = config.buildSessionFactory(serviceRegistry);
}

public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}

Application.java

package com.ranga;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import com.ranga.util.HibernateUtil;

public class Application {
public static void main(String[] args) {
SessionFactory sessionFactory1 = HibernateUtil.getSessionFactory();
Session session1 = null, session2 = null;

session1 = sessionFactory1.openSession();
session2 = sessionFactory1.openSession();

// comparing the session
// Note1
if (session1 == session2) {
System.out.println("Both seesions are equal by using openSession()");
} else {
System.out.println("Both seesions are not equal by using openSession()");
}

session1 = sessionFactory1.getCurrentSession();
session2 = sessionFactory1.getCurrentSession();
// Note2
if (session1 == session2) {
System.out.println("Both seesions are equal by using getCurrentSession()");
} else {
System.out.println("Both seesions are not equal by using getCurrentSession()");
}
}
}

Output:

Both seesions are not equal by using openSession()
Both seesions are equal by using getCurrentSession()


In the Note1 We are checking session1 and session2 (we got sessions by using openSession() method) references are same or not. Here the references are different because when ever we are calling openSession() method it will gives new session. So session1 and session2 are two different sessions.

In the Note2 We are checking session1 and session2 (we got sessions by using getCurrentSession() method) references are same or not. Here the references are same because if we use getCurrentSession() first it will check session exists or not if not exist exist then only it will create new Session. If session already exists that reference only it will use. so session1 and session2 are same references.

Happy Coding ...........

I am waiting for your comments.

1 comments:

akhi said...

Cleared my doubts :) (Y)