Koray Tugay
Koray Tugay

Reputation: 23780

How does getCurrentSession work without openSession?

This is my code:

hibernate.cfg.xml

<?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="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="connection.url">jdbc:mysql://localhost:3306/sakila</property>
        <property name="connection.username">root</property>
        <property name="connection.password"/>

        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>

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

        <mapping class="biz.tugay.saqila.model.Actor" />
    </session-factory>
</hibernate-configuration>

HibernateUtil.java

package biz.tugay.saqila.dao;
/* User: [email protected] Date: 06/08/15 Time: 18:29 */

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;

public class HibernateUtil {

    private static SessionFactory SESSION_FACTORY;

    public static void buildSessionFactory() {
        if (SESSION_FACTORY != null) {
            return;
        }

        Configuration configuration = new Configuration();
        configuration.configure();
        ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
                .applySettings(configuration.getProperties()).build();
        SESSION_FACTORY = configuration.buildSessionFactory(serviceRegistry);

    }

    public static Session getCurrentSession() {
        return SESSION_FACTORY.getCurrentSession();
    }

    public static void killSessionFactory() {
        if (SESSION_FACTORY != null) {
            SESSION_FACTORY.close();
        }
    }

}

and a sample DAO class:

package biz.tugay.saqila.dao;
/* User: [email protected] Date: 06/08/15 Time: 18:37 */

import biz.tugay.saqila.model.Actor;
import org.hibernate.Session;

import java.util.List;

@SuppressWarnings("unchecked")
public class ActorDao {

    public List<Actor> getAllActors() {
        Session session = HibernateUtil.getCurrentSession();
        session.beginTransaction();
        List<Actor> actors = session.createQuery("FROM Actor").list();
        session.close();
        return actors;
    }

    public Actor getWithId(int id) {
        Session session = HibernateUtil.getCurrentSession();
        session.beginTransaction();
        Actor actor = (Actor) session.get(Actor.class, id);
        session.close();
        return actor;
    }

}

Well as you can see I am not calling openSession anywhere, just getCurrentSession. But how does this work?

Also, is this the right way to do things or am I just lucky that this works?

Btw I also have this listener:

package biz.tugay.saqila.servlet;
/* User: [email protected] Date: 06/08/15 Time: 19:00 */


import biz.tugay.saqila.dao.HibernateUtil;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

@WebListener
public class HibernateConfigurator implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        HibernateUtil.buildSessionFactory();
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        System.out.println("Killing Session Factory.");
        HibernateUtil.killSessionFactory();
    }

}

Upvotes: 2

Views: 4658

Answers (2)

Mihir
Mihir

Reputation: 581

If you set hibernate.current_session_context_class to thread, then you can access that session anywhere in application by using the SessionFactory.getCurrentSession().

if you don't want the session to be bound to context then use OpenSession . In some scenario you may need a different session - other than one bound to the context in that case you can use OpenSession instead of currentSession.

SessionFactory.openSession() always opens a new session that you have to close once you are done with the DB operations. SessionFactory.getCurrentSession() returns a session bound to a context and you don't need to close this.

You should never use one session per application - session is not a thread safe object,Which cannot be shared by multiple threads.Always use one session per transaction

Upvotes: 2

JB Nizet
JB Nizet

Reputation: 691715

The javadoc says:

Obtains the current session. The definition of what exactly "current" means controlled by the CurrentSessionContext impl configured for use.

You're using a ThreadLocalSessionContext. Its javadoc says:

A CurrentSessionContext impl which scopes the notion of current session by the current thread of execution. [...] In the interest of usability, it was decided to have this default impl actually generate a session upon first request and then clean it up after the Transaction associated with that session is committed/rolled-back.

You shouldn't close sessions obtained that way. Instead, you should commit the transaction that you have begun. This will close the session, as the documentation says.

Upvotes: 1

Related Questions