org.unitime.timetable.model.base._BaseRootDAO.java Source code

Java tutorial

Introduction

Here is the source code for org.unitime.timetable.model.base._BaseRootDAO.java

Source

/*
 * UniTime 3.2 - 3.5 (University Timetabling Application)
 * Copyright (C) 2008 - 2013, UniTime LLC, and individual contributors
 * as indicated by the @authors tag.
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program 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 General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
*/
package org.unitime.timetable.model.base;

import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.hibernate.Criteria;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.SessionFactory;

import org.hibernate.cfg.Configuration;
import org.hibernate.criterion.Order;
import org.unitime.commons.hibernate.util.DatabaseUpdate;
import org.unitime.commons.hibernate.util.HibernateUtil;

/**
 * @author Tomas Muller
 */
public abstract class _BaseRootDAO<T, K extends Serializable> {

    protected static Map<String, SessionFactory> sSessionFactoryMap;
    protected static SessionFactory sSessionFactory;
    protected static ThreadLocal<HashMap<String, Session>> sMappedSessions;
    protected static ThreadLocal<Session> sSessions;
    protected static Configuration sConfiguration;

    /**
     * Configure the session factory by reading hibernate config file
     */
    public static void initialize() {
        initialize(null);
    }

    /**
     * Configure the session factory by reading hibernate config file
     * @param configFileName the name of the configuration file
     */
    public static void initialize(String configFileName) {
        initialize(configFileName, getNewConfiguration(null));
    }

    @SuppressWarnings("deprecation")
    public static void initialize(String configFileName, Configuration configuration) {
        if (configFileName == null && sSessionFactory != null)
            return;
        if (sSessionFactoryMap != null && sSessionFactoryMap.get(configFileName) != null)
            return;
        HibernateUtil.configureHibernateFromRootDAO(configFileName, configuration);
        sConfiguration = configuration;
        setSessionFactory(configuration.buildSessionFactory());
        HibernateUtil.addBitwiseOperationsToDialect();
        DatabaseUpdate.update();
    }

    /**
     * Set the session factory
     */
    protected static void setSessionFactory(SessionFactory sessionFactory) {
        setSessionFactory(null, sessionFactory);
    }

    /**
     * Set the session factory
     */
    protected static void setSessionFactory(String configFileName, SessionFactory sessionFactory) {
        if (configFileName == null) {
            sSessionFactory = sessionFactory;
        } else {
            if (sSessionFactoryMap == null)
                sSessionFactoryMap = new HashMap<String, SessionFactory>();
            sSessionFactoryMap.put(configFileName, sessionFactory);
        }
    }

    /**
     * Return the SessionFactory that is to be used by these DAOs.  Change this
     * and implement your own strategy if you, for example, want to pull the SessionFactory
     * from the JNDI tree.
     */
    protected SessionFactory getSessionFactory() {
        return getSessionFactory(getConfigurationFileName());
    }

    protected SessionFactory getSessionFactory(String configFile) {
        if (configFile == null) {
            if (sSessionFactory == null)
                throw new RuntimeException(
                        "The session factory has not been initialized (or an error occured during initialization)");
            else
                return sSessionFactory;
        } else {
            if (sSessionFactoryMap == null)
                throw new RuntimeException("The session factory for '" + configFile
                        + "' has not been initialized (or an error occured during initialization)");
            else {
                SessionFactory sessionFactory = (SessionFactory) sSessionFactoryMap.get(configFile);
                if (sessionFactory == null)
                    throw new RuntimeException("The session factory for '" + configFile
                            + "' has not been initialized (or an error occured during initialization)");
                else
                    return sessionFactory;
            }
        }
    }

    /**
     * Return a new Session object that must be closed when the work has been completed.
     * @return the active Session
     */
    public Session getSession() {
        return getSession(getConfigurationFileName(), false);
    }

    /**
     * Return a new Session object that must be closed when the work has been completed.
     * @return the active Session
     */
    public Session createNewSession() {
        return getSession(getConfigurationFileName(), true);
    }

    /**
     * Return a new Session object that must be closed when the work has been completed.
     * @param configFile the config file must match the meta attribute "config-file" in the hibernate mapping file
     * @return the active Session
     */
    private Session getSession(String configFile, boolean createNew) {
        if (createNew) {
            return getSessionFactory(configFile).openSession();
        } else {
            if (configFile == null) {
                if (sSessions == null)
                    sSessions = new ThreadLocal<Session>();
                Session session = sSessions.get();
                if (session == null || !session.isOpen()) {
                    session = getSessionFactory(null).openSession();
                    // session.beginTransaction();
                    sSessions.set(session);
                }
                return session;
            } else {
                if (sMappedSessions == null)
                    sMappedSessions = new ThreadLocal<HashMap<String, Session>>();
                HashMap<String, Session> map = sMappedSessions.get();
                if (map == null) {
                    map = new HashMap<String, Session>();
                    sMappedSessions.set(map);
                }
                Session session = map.get(configFile);
                if (session == null || !session.isOpen()) {
                    session = getSessionFactory(configFile).openSession();
                    // session.beginTransaction();
                    map.put(configFile, session);
                }
                return session;
            }
        }
    }

    /**
     * Get current thread opened session, if there is any
     */
    public Session getCurrentThreadSession() {
        return getCurrentThreadSession(getConfigurationFileName());
    }

    /**
     * Get current thread opened session, if there is any
     */
    private Session getCurrentThreadSession(String configFile) {
        if (configFile == null) {
            if (sSessions != null) {
                Session session = sSessions.get();
                if (session != null)
                    return session;
            }
        } else {
            if (sMappedSessions != null) {
                HashMap<String, Session> map = sMappedSessions.get();
                if (map != null)
                    return map.get(configFile);
            }
        }
        return null;
    }

    /**
     * Close all sessions for the current thread
     */
    public static boolean closeCurrentThreadSessions() {
        return closeCurrentThreadSessions(true);
    }

    /**
     * Rollback all sessions for the current thread
     */
    public static boolean rollbackCurrentThreadSessions() {
        return closeCurrentThreadSessions(false);
    }

    private static boolean closeCurrentThreadSessions(boolean commit) {
        boolean ret = false;
        if (sSessions != null) {
            Session session = sSessions.get();
            if (session != null && session.isOpen()) {
                if (session.getTransaction() != null && session.getTransaction().isActive()) {
                    if (commit)
                        session.getTransaction().commit();
                    else
                        session.getTransaction().rollback();
                }
                session.close();
                ret = true;
            }
            sSessions.remove();
        }
        if (sMappedSessions != null) {
            HashMap<String, Session> map = sMappedSessions.get();
            if (map != null) {
                HibernateException thrownException = null;
                for (Session session : map.values()) {
                    try {
                        if (null != session && session.isOpen()) {
                            if (session.getTransaction() != null && session.getTransaction().isActive()) {
                                if (commit)
                                    session.getTransaction().commit();
                                else
                                    session.getTransaction().rollback();
                            }
                            session.close();
                            ret = true;
                        }
                    } catch (HibernateException e) {
                        thrownException = e;
                    }
                }
                map.clear();
                if (null != thrownException)
                    throw thrownException;
            }
            sMappedSessions.remove();
        }
        return ret;
    }

    /**
     * Begin the transaction related to the session
     */
    public Transaction beginTransaction(Session s) {
        // already in a transaction, do not create a new one
        if (s.getTransaction() != null && s.getTransaction().isActive())
            return null;

        return s.beginTransaction();
    }

    /**
     * Commit the given transaction
     */
    public void commitTransaction(Transaction t) {
        if (t != null)
            t.commit();
    }

    /**
     * Return a new Configuration to use
     */
    public static Configuration getNewConfiguration(String configFileName) {
        return new Configuration();
    }

    /**
     * @return Returns true if configured
     */
    public static boolean isConfigured() {
        return sConfiguration != null && sSessionFactory != null;
    }

    /**
     * @return Returns the configuration.
     */
    public static Configuration getConfiguration() {
        return sConfiguration;
    }

    /**
     * Return the name of the configuration file to be used with this DAO or null if default
     */
    public String getConfigurationFileName() {
        return null;
    }

    /**
     * Return the specific Object class that will be used for class-specific
     * implementation of this DAO.
     * @return the reference Class
     */
    protected abstract Class<T> getReferenceClass();

    /**
     * Used by the base DAO classes but here for your modification
     * Get object matching the given key and return it.
     */
    protected T get(Class<T> refClass, K key) {
        return get(refClass, key, getSession());
    }

    /**
     * Get object matching the given key and return it.
     */
    public T get(K key) {
        return get(getReferenceClass(), key);
    }

    /**
     * Used by the base DAO classes but here for your modification
     * Get object matching the given key and return it.
     */
    @SuppressWarnings("unchecked")
    protected T get(Class<T> refClass, K key, Session s) {
        return (T) s.get(refClass, key);
    }

    /**
     * Get object matching the given key and return it.
     */
    public T get(K key, Session s) {
        return get(getReferenceClass(), key, s);
    }

    /**
     * Used by the base DAO classes but here for your modification
     * Load object matching the given key and return it.
     */
    protected T load(Class<T> refClass, K key) {
        return load(refClass, key, getSession());
    }

    /**
     * Load object matching the given key and return it.
     */
    public T load(K key) {
        return load(getReferenceClass(), key);
    }

    /**
     * Used by the base DAO classes but here for your modification
     * Load object matching the given key and return it.
     */
    @SuppressWarnings("unchecked")
    protected T load(Class<T> refClass, K key, Session s) {
        return (T) s.load(refClass, key);
    }

    /**
     * Load object matching the given key and return it.
     */
    public T load(K key, Session s) {
        return load(getReferenceClass(), key, s);
    }

    /**
     * Load and initialize object matching the given key and return it.
     */
    public T loadInitialize(K key, Session s) {
        T obj = load(key, s);
        if (!Hibernate.isInitialized(obj))
            Hibernate.initialize(obj);
        return obj;
    }

    /**
     * Return all objects related to the implementation of this DAO with no filter.
     */
    public List<T> findAll() {
        Transaction t = null;
        Session s = null;
        try {
            s = getSession();
            t = beginTransaction(s);
            List<T> rtn = findAll(s);
            commitTransaction(t);
            return rtn;
        } catch (HibernateException e) {
            if (null != t)
                t.rollback();
            throw e;
        }
    }

    /**
     * Return all objects related to the implementation of this DAO with no filter.
     * Use the session given.
     * @param s the Session
     */
    public List<T> findAll(Session s) {
        return findAll(s, getDefaultOrder());
    }

    /**
     * Return all objects related to the implementation of this DAO with no filter.
     * The results are ordered by the order specified
     * Use the session given.
     */
    public List<T> findAll(Order... orders) {
        return findAll(getSession(), orders);
    }

    /**
     * Return all objects related to the implementation of this DAO with no filter.
     * Use the session given.
     */
    @SuppressWarnings("unchecked")
    public List<T> findAll(Session s, Order... orders) {
        Criteria crit = s.createCriteria(getReferenceClass());
        if (orders != null) {
            for (Order order : orders) {
                if (order != null)
                    crit.addOrder(order);
            }
        }
        crit.setCacheable(true);
        return (List<T>) crit.list();
    }

    /**
     * Execute a query. 
     * @param queryStr a query expressed in Hibernate's query language
     * @return a distinct list of instances (or arrays of instances)
     */
    public Query getQuery(String queryStr) {
        return getQuery(queryStr, getSession());
    }

    /**
     * Execute a query but use the session given instead of creating a new one.
     * @param queryStr a query expressed in Hibernate's query language
     * @param s the Session to use
     */
    public Query getQuery(String queryStr, Session s) {
        return s.createQuery(queryStr);
    }

    protected Order getDefaultOrder() {
        return null;
    }

    /**
     * Persist the given transient instance, first assigning a generated identifier. 
     * (Or using the current value of the identifier property if the assigned generator is used.) 
     */
    public K save(T obj) {
        Transaction t = null;
        Session s = null;
        try {
            s = getSession();
            t = beginTransaction(s);
            K rtn = save(obj, s);
            commitTransaction(t);
            return rtn;
        } catch (HibernateException e) {
            if (null != t)
                t.rollback();
            throw e;
        }
    }

    /**
     * Persist the given transient instance, first assigning a generated identifier. 
     * (Or using the current value of the identifier property if the assigned generator is used.) 
     */
    @SuppressWarnings("unchecked")
    public K save(T obj, Session s) {
        return (K) s.save(obj);
    }

    /**
     * Either save() or update() the given instance, depending upon the value of its
     * identifier property.
     */
    public void saveOrUpdate(T obj) {
        Transaction t = null;
        Session s = null;
        try {
            s = getSession();
            t = beginTransaction(s);
            saveOrUpdate(obj, s);
            commitTransaction(t);
        } catch (HibernateException e) {
            if (null != t)
                t.rollback();
            throw e;
        }
    }

    /**
     * Either save() or update() the given instance, depending upon the value of its
     * identifier property.
     */
    public void saveOrUpdate(T obj, Session s) {
        s.saveOrUpdate(obj);
    }

    /**
     * Update the persistent state associated with the given identifier. An exception is thrown if there is a persistent
     * instance with the same identifier in the current session.
     * @param obj a transient instance containing updated state
     */
    public void update(T obj) {
        Transaction t = null;
        Session s = null;
        try {
            s = getSession();
            t = beginTransaction(s);
            update(obj, s);
            commitTransaction(t);
        } catch (HibernateException e) {
            if (null != t)
                t.rollback();
            throw e;
        }
    }

    /**
     * Update the persistent state associated with the given identifier. An exception is thrown if there is a persistent
     * instance with the same identifier in the current session.
     * @param obj a transient instance containing updated state
     * @param s the Session
     */
    public void update(T obj, Session s) {
        s.update(obj);
    }

    /**
     * Remove a persistent instance from the datastore. The argument may be an instance associated with the receiving
     * Session or a transient instance with an identifier associated with existing persistent state. 
     */
    public void delete(T obj) {
        Transaction t = null;
        Session s = null;
        try {
            s = getSession();
            t = beginTransaction(s);
            delete(obj, s);
            commitTransaction(t);
        } catch (HibernateException e) {
            if (null != t)
                t.rollback();
            throw e;
        }
    }

    /**
     * Remove a persistent instance from the datastore. The argument may be an instance associated with the receiving
     * Session or a transient instance with an identifier associated with existing persistent state. 
     */
    public void delete(T obj, Session s) {
        s.delete(obj);
    }

    /**
     * Remove a persistent instance from the datastore. The argument may be an instance associated with the receiving
     * Session or a transient instance with an identifier associated with existing persistent state. 
     */
    public void delete(K key) {
        delete(load(key));
    }

    /**
     * Remove a persistent instance from the datastore. The argument may be an instance associated with the receiving
     * Session or a transient instance with an identifier associated with existing persistent state. 
     */
    public void delete(K key, Session s) {
        s.delete(load(key, s));
    }

    /**
     * Re-read the state of the given instance from the underlying database. It is inadvisable to use this to implement
     * long-running sessions that span many business tasks. This method is, however, useful in certain special circumstances.
     */
    public void refresh(T obj, Session s) {
        s.refresh(obj);
    }
}