Hibernate SessionFactory and Session

Understanding the roles of `SessionFactory` and `Session` is crucial. This lesson explains how to create a `SessionFactory` (a factory for `Session` objects) and how to obtain a `Session` for interacting with the database. We will cover session management best practices.


Hibernate SessionFactory and Session

Understanding the roles of SessionFactory and Session is crucial for effective Hibernate usage. This lesson explains how to create a SessionFactory (a factory for Session objects) and how to obtain a Session for interacting with the database. We will cover session management best practices.

Hibernate SessionFactory

The SessionFactory is a heavyweight object responsible for creating Session instances. It is a thread-safe object and should be created only once during application startup. It holds database connection settings, caches compiled mappings for persistent classes, and performs other initializations needed by Hibernate.

Think of the SessionFactory as the factory that produces connections to your database, but it doesn't hold an actual connection itself. It's more like a configuration blueprint.

Creating a SessionFactory

The most common way to create a SessionFactory is using the Configuration class, which reads Hibernate configuration from a configuration file (e.g., hibernate.cfg.xml) or programmatically.

 import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {

    private static final SessionFactory sessionFactory = buildSessionFactory();

    private static SessionFactory buildSessionFactory() {
        try {
            // Create the SessionFactory from hibernate.cfg.xml
            return new Configuration().configure().buildSessionFactory();
        }
        catch (Throwable ex) {
            // Make sure you log the exception, as it might be swallowed
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    public static void shutdown() {
        // Close caches and connection pools
        getSessionFactory().close();
    }

} 

Explanation:

  • HibernateUtil is a utility class (singleton pattern) to manage the SessionFactory.
  • buildSessionFactory() creates the SessionFactory.
  • new Configuration().configure() reads configuration settings from hibernate.cfg.xml (by default). You can also specify the configuration file using configure("hibernate.cfg.xml").
  • buildSessionFactory() builds the SessionFactory object.
  • It's crucial to handle exceptions during SessionFactory creation.
  • getSessionFactory() provides access to the SessionFactory instance.
  • shutdown() gracefully closes the SessionFactory when the application shuts down, releasing resources.

Hibernate Session

The Session is a single-threaded, short-lived object representing a unit of work with the database. It provides the interface between the application and Hibernate. All operations on persistent objects are performed via the Session.

The Session represents a connection to the database. It's important to open and close the session properly to avoid resource leaks.

Obtaining a Session

You obtain a Session from the SessionFactory using the openSession() or getCurrentSession() methods.

 import org.hibernate.Session;
import org.hibernate.SessionFactory;

public class SessionExample {

    public static void main(String[] args) {
        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
        Session session = null;

        try {
            session = sessionFactory.openSession();
            session.beginTransaction();

            // Perform database operations here (e.g., save, update, delete, load)
            // Example:  session.save(new MyEntity());

            session.getTransaction().commit();
        } catch (Exception e) {
            if (session != null && session.getTransaction() != null) {
                System.err.println("Transaction rolling back.");
                session.getTransaction().rollback();
            }
            e.printStackTrace();
        } finally {
            if (session != null) {
                session.close();
            }
        }

        HibernateUtil.shutdown(); // Shutdown the SessionFactory at the end of the application
    }
} 

Explanation:

  • sessionFactory.openSession() opens a new Session. This is the most common way to obtain a session. It is your responsibility to close the session.
  • session.beginTransaction() starts a transaction. All database operations should be performed within a transaction.
  • session.getTransaction().commit() commits the transaction, persisting changes to the database.
  • session.getTransaction().rollback() rolls back the transaction if an exception occurs, preventing inconsistent data.
  • session.close() closes the session, releasing resources. It's crucial to close the session in a finally block to ensure it's always closed, even if an exception occurs.
  • The try-catch-finally block ensures proper session management and rollback in case of errors.

Session Management Best Practices

  • Open and Close Sessions Appropriately: Always open a session when you need to perform database operations and close it as soon as you are finished. Use a try-finally block to guarantee session closure.
  • Use Transactions: Enclose all database operations within a transaction to ensure data consistency and atomicity.
  • Rollback on Errors: Rollback transactions if any exception occurs during the database operations.
  • Avoid Long-Lived Sessions: Sessions should be short-lived and used for a single unit of work. Long-lived sessions can lead to performance issues and increased memory consumption.
  • Understand Session Scopes: Consider using getCurrentSession() in web applications with a framework that provides a session-per-request pattern (e.g., Spring). This will automatically manage the session for each request. You need to configure the current_session_context_class property in your hibernate configuration.
  • Use StatelessSession for Batch Processing: For high-volume, read-only batch processing, consider using StatelessSession. It offers better performance by bypassing the first-level cache and other features of a regular Session.

Summary

The SessionFactory is a heavyweight, thread-safe object that creates Session instances. The Session is a single-threaded object representing a unit of work with the database. Proper session management, including opening, closing, and handling transactions, is crucial for building robust and efficient Hibernate applications.