net.databinder.hib.Databinder.java Source code

Java tutorial

Introduction

Here is the source code for net.databinder.hib.Databinder.java

Source

/*
 * Databinder: a simple bridge from Wicket to Hibernate
 * Copyright (C) 2006  Nathan Hamblen nathan@technically.us
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

package net.databinder.hib;

import org.apache.wicket.Application;
import org.apache.wicket.WicketRuntimeException;
import org.apache.wicket.request.cycle.RequestCycle;
import org.hibernate.SessionFactory;
import org.hibernate.context.internal.ManagedSessionContext;

/**
 * Provides access to application-bound Hibernate session factories and current sessions.
 * This class will work with a
 * <a href="http://www.hibernate.org/hib_docs/v3/api/org/hibernate/context/ManagedSessionContext.html">ManagedSessionContext</a>
 * and DataRequestCycle listener when present, but neither is required so long as a
 * "current" session is available from the session factory supplied by the application.
 * @see HibernateApplication
 * @author Nathan Hamblen
 */
public class Databinder {

    /**
     * @return default session factory, as returned by the application
     * @throws WicketRuntimeException if session factory can not be found 
     * @see HibernateApplication
     */
    public static SessionFactory getHibernateSessionFactory() {
        return getHibernateSessionFactory(null);
    }

    /**
     * @param key object, or null for the default factory
     * @return session factory, as returned by the application
     * @throws WicketRuntimeException if session factory can not be found 
     * @see HibernateApplication
     */
    public static SessionFactory getHibernateSessionFactory(Object key) {
        Application app = Application.get();
        if (app instanceof HibernateApplication)
            return ((HibernateApplication) app).getHibernateSessionFactory(key);
        throw new WicketRuntimeException("Please implement HibernateApplication in your Application subclass.");
    }

    /**
     * @return default Hibernate session bound to current thread
     */
    public static org.hibernate.Session getHibernateSession() {
        return getHibernateSession(null);
    }

    /**
     * @param key or null for the default factory
     * @return Hibernate session bound to current thread
     */
    public static org.hibernate.Session getHibernateSession(Object key) {
        dataSessionRequested(key);
        return getHibernateSessionFactory(key).getCurrentSession();
    }

    /**
     * @return true if a session is bound for the default factory
     */
    public static boolean hasBoundSession() {
        return hasBoundSession(null);
    }

    /**
     * @param key or null for the default factory
     * @return true if a session is bound for the keyed factory
     */
    public static boolean hasBoundSession(Object key) {
        return org.hibernate.context.internal.ManagedSessionContext.hasBind(getHibernateSessionFactory(key));
    }

    /**
     * Notifies current request cycle that a data session was requested, if a session factory
     * was not already bound for this thread and the request cycle is an DataRequestCycle.
     * @param key or null for the default factory
     * @see HibernateRequestCycle
     */
    private static void dataSessionRequested(Object key) {
        if (!hasBoundSession(key)) {
            // if session is unavailable, it could be a late-loaded conversational cycle
            RequestCycle cycle = RequestCycle.get();
            if (cycle instanceof HibernateRequestCycle)
                ((HibernateRequestCycle) cycle).dataSessionRequested(key);
        }
    }

    /**
     * Wraps SessionUnit callback in a temporary thread-bound Hibernate session from the default
     * factory if necessary. This is to be used outside of a regular a session-handling request cycle,
     * such as during application init or an external Web service request. 
     * The temporary session and transaction, if created, are closed after the callback returns and 
     * uncommited transactions are rolled back. Be careful of returning detached Hibernate 
     * objects that may not be fully loaded with data; consider using projections / scalar 
     * queries instead.<b>Note</b> This method uses a ManagedSessionContext. With JTA
     * or other forms of current session lookup a wrapping session will not be
     * detected and a new one will always be created.
     * @param unit work to be performed in thread-bound session
     * @see SessionUnit
     */
    public static Object ensureSession(SessionUnit unit) {
        return ensureSession(unit, null);
    }

    /**
     * Wraps SessionUnit callback in a temporary thread-bound Hibernate session from the keyed
     * factory if necessary. This is to be used outside of a regular a session-handling request cycle,
     * such as during application init or an external Web service request. 
     * The temporary session and transaction, if created, are closed after the callback returns and 
     * uncommited transactions are rolled back. Be careful of returning detached Hibernate 
     * objects that may not be fully loaded with data; consider using projections / scalar 
     * queries instead. <b>Note</b> This method uses a ManagedSessionContext. With JTA
     * or other forms of current session lookup a wrapping session will not be
     * detected and a new one will always be created. 
     * @param unit work to be performed in thread-bound session
     * @param key or null for the default factory
     * @see SessionUnit
     */
    public static Object ensureSession(SessionUnit unit, Object key) {
        dataSessionRequested(key);
        SessionFactory sf = getHibernateSessionFactory(key);
        if (ManagedSessionContext.hasBind(sf))
            return unit.run(getHibernateSession(key));
        org.hibernate.Session sess = sf.openSession();
        try {
            sess.beginTransaction();
            ManagedSessionContext.bind(sess);
            return unit.run(sess);
        } finally {
            try {
                if (sess.getTransaction().isActive())
                    sess.getTransaction().rollback();
            } finally {
                sess.close();
                ManagedSessionContext.unbind(sf);
            }
        }
    }
}