Subversion Repositories general

Rev

Rev 1020 | Blame | Last modification | View Log | RSS feed

package ak.hostadmiral.util;

import java.util.Iterator;
import java.util.Collection;
import java.util.Map;
import java.util.List;
import java.util.ArrayList;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import net.sf.hibernate.*;
import net.sf.hibernate.cfg.*;
import net.sf.hibernate.type.Type;

public class HibernateUtil
{
        public static final int DATABASE_VERSION = 1;

        private static       Configuration  configuration;
        private static       SessionFactory sessionFactory;
        private static final ThreadLocal    hibernateBean = new ThreadLocal();
    private static       boolean        validated     = false;

    private static void validate()
                throws HibernateException, ModelException
    {
        synchronized(HibernateUtil.class) {
                if(validated) return;

                        Collection versions = currentSession().find("from DatabaseVersion");

            if(versions == null || versions.size() == 0)
                throw new ModelException("Database structure version not found");

            if(versions.size() > 1)
                throw new ModelException("Too much entries in database structure version table");

            int version = ((DatabaseVersion)versions.iterator().next()).getVersion();
            if(version != DATABASE_VERSION)
                throw new ModelException("Expected database structure version "
                        + DATABASE_VERSION + ", found " + version);

                validated = true;
        }
    }

        public static Configuration getConfiguration()
                throws HibernateException
        {
                if(configuration == null)
                        configuration = new Configuration();

                return configuration;
        }

        public static SessionFactory getSessionFactory()
                throws HibernateException
        {
                if(sessionFactory == null)
                        sessionFactory = getConfiguration().configure().buildSessionFactory();

                return sessionFactory;
        }

        private static HibernateBean currentBean()
                throws HibernateException
        {
                HibernateBean hb = (HibernateBean)hibernateBean.get();

                if(hb == null) {
                        hb = new HibernateBean();
                        hb.session = getSessionFactory().openSession();
                        hibernateBean.set(hb);
                }
                return hb;
        }

        public static Session currentSession()
                throws HibernateException
        {
                return currentBean().session;
        }

        public static void closeSession()
                throws HibernateException, ModelException
        {
                HibernateBean hb = (HibernateBean)hibernateBean.get();

                if(hb == null)
                        throw new ModelException("No session found for this thread");

                hibernateBean.set(null);
                hb.session.close();
        }

        public static void beginTransaction()
                throws HibernateException, ModelException
        {
                HibernateBean hb = (HibernateBean)hibernateBean.get();

                if(hb != null && hb.transaction != null)
                        throw new ModelException("Transaction is already open");

                currentBean().transaction = currentSession().beginTransaction();

                // validate database structure version
        if(!validated) // just try to speed up by avoiding synchronization
                        validate();
        }

        public static boolean isTransactionOpen()
                throws HibernateException, ModelException
        {
                HibernateBean hb = (HibernateBean)hibernateBean.get();

                return (hb != null) && (hb.transaction != null);
        }

        public static void commitTransaction()
                throws HibernateException, ModelException
        {
                HibernateBean hb = (HibernateBean)hibernateBean.get();

                if(hb == null || hb.transaction == null)
                        throw new ModelException("No open transaction");

                hb.transaction.commit();
                hb.transaction = null;
        }

        public static void rollbackTransaction()
                throws HibernateException, ModelException
        {
                HibernateBean hb = (HibernateBean)hibernateBean.get();

                if(hb == null || hb.transaction == null)
                        throw new ModelException("No open transaction");

                hb.transaction.rollback();
                hb.transaction = null;
        }

    public static List sqlQuery(String query, Object[] values)
                throws ModelException
    {
        Connection        con;
        PreparedStatement stmt;

        try {
                con = currentSession().connection();
        }
        catch(HibernateException ex) {
                        throw new ModelException(ex);
        }

        try {
                stmt = con.prepareStatement(query);
        }
        catch(SQLException ex) {
                        throw new ModelException(ex);
        }

                try {
                        if(values != null) {
                                for(int i = 0; i < values.length; i++)
                                        stmt.setObject(i+1, values[i]);
                        }

                        List res = new ArrayList();
                        ResultSet rs = stmt.executeQuery();
                        while(rs.next()) {
                                res.add(rs.getObject(1));
                        }
                        return res;
                }
                catch(SQLException ex)
                {
                        throw new ModelException(ex);
                }
                finally {
                try {
                                stmt.close();
                        }
                        catch(SQLException ex) {
                                ex.printStackTrace();
                        }
                }
    }

    public static List pageableList(int pageSize, int pageNumber,
                        String query, Class classToLoad, String[] returnAliases, Class[] returnClasses,
                        Object[] values, Type[] types)
                throws ModelException
    {
                try {
                        Query hq = currentSession().createSQLQuery(
                                query, returnAliases, returnClasses);

                        if(values != null && types != null) {
                                for(int i  = 0; i < values.length; i++)
                                        hq.setParameter(i, values[i], types[i]);
                        }

                        if(pageSize > 0) {
                                hq.setFirstResult(pageSize * pageNumber);
                                hq.setMaxResults(pageSize);
                        }

                        return selectClassColumn(classToLoad, hq.list());
                        // FIXME: really no other way in Hibernate?
                }
                catch(HibernateException ex)
                {
                        throw new ModelException(ex);
                }
    }

        protected static List selectClassColumn(Class classToLoad, List list)
                throws ModelException
        {
                List res = new ArrayList();

                if(list == null || list.size() == 0) return res;

                Object o = list.get(0);
                if(o == null)
                        throw new ModelException(
                                "First element in the list is null, cannot determine it type");

                if(!(o instanceof Object[])) {
                        if(classToLoad.isInstance(o))
                                return list;
                        else
                                throw new ModelException("First element in the list is instance of "
                                        + o.getClass().getName() + ", which is not java.lang.Object[] or "
                                        + classToLoad.getName());
                }

        Object[] oa = (Object[])o;
        int      pos = -1;

        for(int i = 0; i < oa.length; i++) {
                if(classToLoad.isInstance(oa[i])) {
                        if(pos < 0)
                                pos = i;
                        else
                                        throw new ModelException("First row of the list has several elements of type "
                                                + classToLoad.getName());
                }
        }
        if(pos < 0) {
                        throw new ModelException("First row of the list has no elements of type "
                                + classToLoad.getName());
        }

        for(Iterator i = list.iterator(); i.hasNext(); ) {
                Object[] e = (Object[])i.next();
                res.add(e[pos]);
        }

                return res;
        }

        public static String formOrderClause(Integer[] sortingKeys, Map fieldMap)
                throws ModelException
        {
                if(sortingKeys == null || sortingKeys.length == 0) return "";

                StringBuffer buf = new StringBuffer(" order by ");

                for(int i = 0; i < sortingKeys.length; i++) {
                        if(i > 0) buf.append(",");

                        String field = (String)fieldMap.get(sortingKeys[i]);
                        if(field == null)
                                throw new ModelException(
                                        "Field for sorting key " + sortingKeys[i] + " not found");

                        buf.append(field);
                }

                return buf.toString();
        }

        static class HibernateBean
        {
                public Session     session;
                public Transaction transaction;
        }
}