fr.gael.dhus.database.dao.interfaces.HibernateDao.java Source code

Java tutorial

Introduction

Here is the source code for fr.gael.dhus.database.dao.interfaces.HibernateDao.java

Source

/*
 * Data Hub Service (DHuS) - For Space data distribution.
 * Copyright (C) 2013,2014,2015 GAEL Systems
 *
 * This file is part of DHuS software sources.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package fr.gael.dhus.database.dao.interfaces;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.DetachedCriteria;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.support.DataAccessUtils;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import javax.swing.event.EventListenerList;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.sql.SQLException;
import java.util.Date;
import java.util.List;

/**
 * Hibernate DAO Implementation, containing minimal CRUD operations.
 * 
 * @param <T> Object concerned by this DAO
 * @param <PK> Primary Key of this Object.
 */
public class HibernateDao<T, PK extends Serializable> extends HibernateDaoSupport
        implements GenericDao<T, PK>, Pageable<T> {
    protected Class<T> entityClass;
    private final EventListenerList listeners = new EventListenerList();

    @SuppressWarnings("unchecked")
    public HibernateDao() {
        ParameterizedType genericSuperclass = (ParameterizedType) getClass().getGenericSuperclass();
        this.entityClass = (Class<T>) genericSuperclass.getActualTypeArguments()[0];
    }

    @SuppressWarnings("unchecked")
    @Override
    public T create(T t) {
        T sent = t;
        long start = new Date().getTime();
        PK id = (PK) getHibernateTemplate().save(t);
        t = getHibernateTemplate().get((Class<T>) t.getClass(), id);
        long end = new Date().getTime();
        logger.info("Create/save " + entityClass.getSimpleName() + "(" + id + ") spent " + (end - start) + "ms");

        fireCreatedEvent(new DaoEvent<T>(sent));
        return t;
    }

    @Override
    public T read(PK id) {
        long start = new Date().getTime();
        T ret = getHibernateTemplate().get(entityClass, id);
        long end = new Date().getTime();
        logger.debug("Read " + entityClass.getSimpleName() + "(" + id + ") spent " + (end - start) + "ms");
        return ret;
    }

    @Override
    public void update(T t) {
        long start = new Date().getTime();
        getHibernateTemplate().update(t);
        long end = new Date().getTime();
        logger.info("Update " + entityClass.getSimpleName() + " spent " + (end - start) + "ms");

        fireUpdatedEvent(new DaoEvent<T>(t));
    }

    /**
     * Merge the provided object into the current session.
     * This could be useful when one session handle the same object twice.
     * @param t the entity to merge.
     */
    public void merge(T t) {
        long start = new Date().getTime();
        getHibernateTemplate().getSessionFactory().getCurrentSession().merge(t);
        long end = new Date().getTime();
        logger.info("Merge " + entityClass.getSimpleName() + " spent " + (end - start) + "ms");
    }

    @Override
    public void delete(T t) {
        long start = new Date().getTime();
        getHibernateTemplate().delete(t);
        long end = new Date().getTime();
        logger.info("Delete " + entityClass.getSimpleName() + " spent " + (end - start) + "ms");

        fireDeletedEvent(new DaoEvent<T>(t));
    }

    /**
     * Remove all the element from the db og this <T> instance.
     */
    public void deleteAll() {
        for (T entity : readAll())
            delete(entity);

        //      String hql = "DELETE FROM " + entityClass.getName ();
        //      getHibernateTemplate ().bulkUpdate (hql);
    }

    /**
     * <p>Returns a List of <b>T</b> entities, where HQL clauses can be
     * specified.</p>
     * 
     * Note: This method is useful in read only. It can be use to delete or 
     * create <b>T</b> entities, but caution with <code>top</code> and 
     * <code>skip</code> arguments.
     * 
     * @param clauses query clauses (WHERE, ORDER BY, GROUP BY), if null no
     * clauses are apply.
     * @param skip number of entities to skip.
     * @param n  number of entities max returned.
     * @return a list of <b>T</b> entities.
     */
    @SuppressWarnings("unchecked")
    public List<T> scroll(final String clauses, final int skip, final int n) {
        StringBuilder hql = new StringBuilder();
        hql.append("FROM ").append(entityClass.getName());
        if (clauses != null)
            hql.append(" ").append(clauses);

        Session session;
        boolean newSession = false;
        try {
            session = getSessionFactory().getCurrentSession();
        } catch (HibernateException e) {
            session = getSessionFactory().openSession();
            newSession = true;
        }

        Query query = session.createQuery(hql.toString());
        if (skip > 0)
            query.setFirstResult(skip);
        if (n > 0) {
            query.setMaxResults(n);
            query.setFetchSize(n);
        }

        logger.info("Execution of HQL: " + hql.toString());
        long start = System.currentTimeMillis();

        List<T> result = (List<T>) query.list();
        logger.info("HQL executed in " + (System.currentTimeMillis() - start) + "ms.");

        if (newSession) {
            session.disconnect();
        }

        return result;
    }

    /**
     * Retrieve the first element of the results.
     * 
     * @param query_string
     * @return
     */
    public T first(String query_string) {
        @SuppressWarnings("unchecked")
        List<T> result = (List<T>) getHibernateTemplate().find(query_string);
        return (result.isEmpty()) ? null : result.get(0);
    }

    /**
     * Returns all Objects in a List.
     * 
     * @return List containing all Objects.
     */
    @SuppressWarnings("unchecked")
    @Override
    public List<T> readAll() {
        return find("FROM " + entityClass.getName());
    }

    /**
     * Count objects in table.
     * 
     * @return Objects count.
     */
    public int count() {
        int count = 0;
        @SuppressWarnings("unchecked")
        List<Long> counts = find("select count(*) FROM " + entityClass.getName());
        if (counts != null)
            for (Long c : counts)
                count += c;
        return count;
    }

    @SuppressWarnings("rawtypes")
    public List find(String query_string) throws DataAccessException {
        long start = new Date().getTime();
        List ret = getHibernateTemplate().find(query_string);

        long end = new Date().getTime();
        logger.debug(
                "Query \"" + query_string.replaceAll("(\\r|\\n)", " ").trim() + "\" spent " + (end - start) + "ms");
        return ret;
    }

    public void addListener(DaoListener<T> listener) {
        listeners.add(DaoListener.class, listener);
    }

    public void removeListener(DaoListener<T> listener) {
        listeners.remove(DaoListener.class, listener);
    }

    @SuppressWarnings("unchecked")
    public DaoListener<T>[] getListeners() {
        return listeners.getListeners(DaoListener.class);
    }

    protected void fireCreatedEvent(DaoEvent<T> e) {
        for (DaoListener<T> listener : getListeners()) {
            listener.created(e);
        }
    }

    protected void fireUpdatedEvent(DaoEvent<T> e) {
        for (DaoListener<T> listener : getListeners()) {
            listener.updated(e);
        }
    }

    protected void fireDeletedEvent(DaoEvent<T> e) {
        for (DaoListener<T> listener : getListeners()) {
            listener.deleted(e);
        }
    }

    @Autowired
    public void init(SessionFactory session_factory) {
        setSessionFactory(session_factory);
    }

    public void printCurrentSessions() {
        int num_session = countOpenSessions();
        logger.info(countOpenSessions() + " open sessions:");
        int index = 0;
        while (index < num_session) {
            logger.info("   SESSION_ID       " + getSystemByName("SESSION_ID", index));
            logger.info("   CONNECTED        " + getSystemByName("CONNECTED", index));
            logger.info("   SCHEMA           " + getSystemByName("SCHEMA", index));
            //logger.info(
            //   "TRANSACTION      "+ getSystemByName("TRANSACTION", index));
            logger.info("   WAITING_FOR_THIS " + getSystemByName("WAITING_FOR_THIS", index));
            logger.info("   THIS_WAITING_FOR " + getSystemByName("THIS_WAITING_FOR", index));
            logger.info("   LATCH_COUNT      " + getSystemByName("LATCH_COUNT", index));
            logger.info("   STATEMENT        " + getSystemByName("CURRENT_STATEMENT", index));
            logger.info("");
            index++;
        }
    }

    @SuppressWarnings("rawtypes")
    private int countOpenSessions() {
        return DataAccessUtils.intResult(getHibernateTemplate().execute(new HibernateCallback<List>() {
            @Override
            public List doInHibernate(Session session) throws HibernateException, SQLException {
                String sql = "SELECT count (*) FROM INFORMATION_SCHEMA.SYSTEM_SESSIONS";
                SQLQuery query = session.createSQLQuery(sql);
                return query.list();
            }
        }));
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    private String getSystemByName(final String name, final int index) {
        return DataAccessUtils.uniqueResult(getHibernateTemplate().execute(new HibernateCallback<List>() {
            @Override
            public List doInHibernate(Session session) throws HibernateException, SQLException {
                String sql = "SELECT " + name + " FROM INFORMATION_SCHEMA.SYSTEM_SESSIONS" + " LIMIT  1 OFFSET "
                        + index;
                SQLQuery query = session.createSQLQuery(sql);
                return query.list();
            }
        })).toString();
    }

    /**
     * Returns a paged list of database entities.
     * 
     * @param query the passed query to retrieve the list.
     * @param skip the number of elements to skip in the list (0=no skip).
     * @param top number of element to be retained in the list.
     * @throws ClassCastException if query does not returns entity list of type T.
     * @see org.hibernate.Query
     */
    @Override
    public List<T> getPage(final String query, final int skip, final int top) {
        return getHibernateTemplate().execute(new HibernateCallback<List<T>>() {
            // List must be instance of List<T> otherwise ClassCast
            @SuppressWarnings("unchecked")
            @Override
            public List<T> doInHibernate(Session session) throws HibernateException, SQLException {
                Query hql_query = session.createQuery(query);
                hql_query.setFirstResult(skip);
                hql_query.setMaxResults(top);
                return hql_query.list();
            }
        });
    }

    @SuppressWarnings("unchecked")
    public List<T> listCriteria(DetachedCriteria detached, int skip, int top) {
        SessionFactory factory = getSessionFactory();
        org.hibernate.classic.Session session = factory.getCurrentSession();

        Criteria criteria = detached.getExecutableCriteria(session);

        if (skip > 0)
            criteria.setFirstResult(skip);
        if (top > 0)
            criteria.setMaxResults(top);
        return criteria.list();
    }

    @SuppressWarnings("unchecked")
    public T uniqueResult(DetachedCriteria criteria) {
        return (T) criteria.getExecutableCriteria(getSessionFactory().getCurrentSession()).uniqueResult();
    }

    public int count(DetachedCriteria detached) {
        Session session = getSessionFactory().getCurrentSession();
        Criteria criteria = detached.getExecutableCriteria(session);
        Object result = criteria.uniqueResult();
        return ((Number) result).intValue();
    }
}