cz.jirutka.commons.hibernate.HibernateGenericDAO.java Source code

Java tutorial

Introduction

Here is the source code for cz.jirutka.commons.hibernate.HibernateGenericDAO.java

Source

/*
 * Copyright (c) 2012 Jakub Jirutka <jakub@jirutka.cz>
 *
 * This program 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 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 Lesser General Public License for
 * more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package cz.jirutka.commons.hibernate;

import cz.jirutka.commons.hibernate.criteria.ExtendedCriteria;
import cz.jirutka.commons.persistence.Persistable;
import cz.jirutka.commons.persistence.dao.GenericDAO;
import cz.jirutka.commons.persistence.dao.PagingOrdering;
import java.io.Serializable;
import java.util.Arrays;
import java.util.List;
import javax.persistence.NoResultException;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Example;
import org.hibernate.criterion.Example.PropertySelector;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.metadata.ClassMetadata;
import org.hibernate.type.Type;

/**
 * Hibernate implementation of the {@link GenericDAO} interface.
 *
 * @author Jakub Jirutka <jakub@jirutka.cz>
 * @version 2012-07-09
 * @since 1.1
 */
public class HibernateGenericDAO implements GenericDAO {

    public static final String CACHE_REGION_NATURAL_ID = "org.hibernate.cache.region.NaturalIdentifiersCache";

    protected final SessionFactory sessionFactory;

    /**
     * Create a new instance of the Hibernate GenericDAO.
     * 
     * @param sessionFactory Hibernate Session Factory
     */
    public HibernateGenericDAO(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    @Override
    public Long count(Class<? extends Persistable> clazz) {
        return (Long) session().createCriteria(clazz).setProjection(Projections.rowCount()).list().get(0);
    }

    @Override
    public void delete(Persistable entity) {
        session().delete(entity);
    }

    @Override
    public void delete(Serializable id, Class<? extends Persistable> clazz) throws NoResultException {
        String className = clazz.getSimpleName();

        int deleted = session().createQuery("DELETE " + className + " AS e " + "WHERE e.id = :id")
                .setParameter("id", id).executeUpdate();

        if (deleted == 0) {
            throw new NoResultException(String.format("No such entity %s with id = %s", className, id));
        }
    }

    @Override
    public <E extends Persistable> E findByPrimaryKey(Serializable id, Class<E> clazz) throws NoResultException {

        E entity = (E) session().get(clazz, id);

        if (entity == null) {
            throw new NoResultException(String.format("No such entity %s with id = %s", clazz.getSimpleName(), id));
        }
        return entity;
    }

    @Override
    public <E extends Persistable> List<E> getAll(Class<E> clazz) {

        return session().createCriteria(clazz).list();
    }

    @Override
    public <E extends Persistable> List<E> findByExample(E exampleInstance, String[] includeProperties,
            PagingOrdering paging, Class<E> clazz) {

        final List<String> properties = Arrays.asList(includeProperties);
        PropertySelector selector = new Example.PropertySelector() {
            public boolean include(Object propertyValue, String propertyName, Type type) {
                return properties.contains(propertyName);
            }
        };
        return createCriteria(clazz).add(Example.create(exampleInstance).setPropertySelector(selector))
                .setPagingOrdering(paging).list();
    }

    @Override
    public <E extends Persistable> E findByNaturalKey(Object key, Class<E> clazz) throws NoResultException {

        String className = clazz.getSimpleName();
        ClassMetadata metadata = sessionFactory.getClassMetadata(clazz);
        String[] names = HibernateUtils.getNaturalIdentifierNames(metadata);

        if (names.length == 0) {
            throw new IllegalArgumentException(
                    String.format("Entity class %s does not contain NaturalId", className));
        }
        if (names.length > 1) {
            throw new IllegalArgumentException(String
                    .format("Entity class %s has more than one property with @NaturalId annotation", className));
        }

        return findByNaturalKey(names[0], key, clazz);
    }

    public <E extends Persistable> E findByNaturalKey(String property, Object value, Class<E> clazz)
            throws NoResultException {

        E entity = (E) createCriteria(clazz).add(Restrictions.naturalId().set(property, value)).setCacheable(true)
                .setCacheRegion(CACHE_REGION_NATURAL_ID).uniqueResult();

        if (entity == null) {
            throw new NoResultException(String.format("No such entity %s with NaturalId %s = %s",
                    clazz.getSimpleName(), property, value));
        }
        return entity;
    }

    @Override
    public <E extends Persistable> List<E> findByProperty(String property, Object value, PagingOrdering paging,
            Class<E> clazz) {

        return createCriteria(clazz).add(Restrictions.eq(property, value)).setPagingOrdering(paging).list();
    }

    @Override
    public <E extends Persistable> List<E> getPaginated(PagingOrdering paging, Class<E> clazz) {

        return createCriteria(clazz).setPagingOrdering(paging).list();
    }

    @Override
    public boolean isPersistent(Serializable id, Class<? extends Persistable> clazz) {
        Long result = (Long) session().createCriteria(clazz).add(Restrictions.idEq(id))
                .setProjection(Projections.rowCount()).uniqueResult();
        return (result == 1) ? true : false;
    }

    @Override
    public <E extends Persistable> E load(Serializable id, Class<E> clazz) {

        return (E) session().load(clazz, id);
    }

    @Override
    public Serializable save(Persistable entity) {
        return session().save(entity);
    }

    @Override
    public void saveOrUpdate(Persistable entity) {
        session().saveOrUpdate(entity);
    }

    @Override
    public void update(Persistable entity) {
        session().update(entity);
    }

    /**
     * Create a new <tt>Criteria</tt> for the given entity class and decorate
     * it with the {@linkplain VisitableCriteria}.
     * 
     * @see Session#createCriteria(java.lang.Class) 
     * 
     * @param persistentClass an entity class
     * @return the decorated criteria instance
     */
    protected ExtendedCriteria createCriteria(Class<? extends Persistable> persistentClass) {

        Criteria criteria = session().createCriteria(persistentClass);
        return new ExtendedCriteria(criteria);
    }

    /**
     * Return the current Hibernate Session for this thread.
     * 
     * @return the Hibernate Session
     */
    protected Session session() {
        return sessionFactory.getCurrentSession();
    }

}