com.billing.ng.dao.impl.GenericDAOImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.billing.ng.dao.impl.GenericDAOImpl.java

Source

/*
 BillingNG, a next-generation billing solution
 Copyright (C) 2010 Brian Cowdery
    
 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/agpl-3.0.html
 */

package com.billing.ng.dao.impl;

import com.billing.ng.dao.GenericDAO;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Example;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;

import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.LockModeType;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;

/**
 * GenericDAO implementation, based heavily on Christian Bauer's generic DAO from the
 * Hibernate example Caveat Emptor application.
 *
 *  see https://www.hibernate.org/328.html
 *
 * This implementation relies on Container Managed Transactions (CMT) and Persistence
 * Context injection (also provided by the container). Some method's require Hibernate
 * as the underlying persistence provider and will throw an exception if the hibernate Session
 * could not be retrieved (e.g., {@link #getSession()}).
 *
 * @param <T>
 * @param <ID>
 *
 * @author Brian Cowdery
 * @since 2-Sep-2009
 */
public abstract class GenericDAOImpl<T, ID extends Serializable> implements GenericDAO<T, ID> {

    @Inject
    private EntityManager entityManager;
    private transient Session session;

    private Class<T> entityBeanType;

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

    public void setEntityManager(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    protected EntityManager getEntityManager() {
        if (entityManager == null)
            throw new IllegalStateException("EntityManager has not been set on DAO prior to usage");
        return entityManager;
    }

    /**
     * Returns a hibernate Session from the EntityManager, which requires that Hibernate
     * be the underlying persistence provider - and that EntityManager#getDelegate() will
     * return a Session object in this case. JPA specifications on EntityManager#getDelegate()
     * are spotty and known to be problematic in some environments.
     *
     * @return Hibernate Session
     */
    protected Session getSession() {
        if (session == null || !session.isOpen()) {
            Object o = getEntityManager().getDelegate();

            if (!(o instanceof Session))
                throw new UnsupportedOperationException("Hibernate is not the underlying Persistence provider,"
                        + " or EntityManager#getDelegate() unsupported.");
            session = (Session) o;
        }

        return session;
    }

    protected Class<T> getEntityBeanType() {
        return entityBeanType;
    }

    /**
     * @see javax.persistence.EntityManager#flush()
     */
    protected void flush() {
        getEntityManager().flush();
    }

    /**
     * @see javax.persistence.EntityManager#clear()
     */
    protected void clear() {
        getEntityManager().clear();
    }

    /**
     * Persists the specified entity to the database, returning the newly persisted entity.
     *
     * @param entity entity to persist
     * @return T persisted entity
     * @see javax.persistence.EntityManager#persist(Object)
     */
    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public T persist(T entity) {
        getEntityManager().persist(entity);
        return entity;
    }

    /**
     * Updates/merges the specified entity to the database, returning the newly updated entity.
     *
     * @param entity entity to update
     * @return T updated entity
     * @see javax.persistence.EntityManager#merge(Object)
     */
    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public T update(T entity) {
        return getEntityManager().merge(entity);
    }

    /**
     * Deletes/removes the specified entity from the database.
     *
     * @param entity entity to update
     * @see javax.persistence.EntityManager#remove(Object)
     */
    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public void delete(T entity) {
        if (isManaged(entity)) {
            getEntityManager().remove(entity);
        } else {
            getEntityManager().remove(getEntityManager().merge(entity));
        }
    }

    /**
     * Returns true if the given entity is associated with the current persistence context.
     *
     * @param entity entity to check
     * @return true if entity is managed, false if not
     */
    public boolean isManaged(T entity) {
        return getEntityManager().contains(entity);
    }

    /**
     * Returns true if a persisted record exsits for the given id.
     *
     * This method requires an underlying Hibernate persistence provider.
     *
     * @param id primary key of entity
     * @return true if entity exists for id, false if entity does not exist
     */
    public boolean isIdPersisted(ID id) {
        Criteria criteria = createCritiera().add(Restrictions.idEq(id)).setProjection(Projections.id());

        return !criteria.list().isEmpty();
    }

    /**
     * Finds an entity by its primary key, optionally locking the entity for
     * exclusive write access.
     *
     * @param id primary key of entity
     * @param lock whether or not to lock entity for exclusive write access
     * @return T entity of type T
     * @see javax.persistence.EntityManager#lock(Object, javax.persistence.LockModeType)
     */
    public T findById(ID id, boolean lock) {
        T entity = getEntityManager().find(getEntityBeanType(), id);

        if (lock)
            getEntityManager().lock(entity, LockModeType.WRITE);

        return entity;
    }

    /**
     * Returns a list of all entities of this type T present within the database.
     *
     * @return List<T> list of entities of type T
     */
    @SuppressWarnings("unchecked")
    public List<T> findAll() {
        return getEntityManager().createQuery("from " + getEntityBeanType().getName()).getResultList();
    }

    /**
     * Finds similar entities to the provided example, excluding an explicitly
     * ignored properties (as strings).
     *
     * This method requires an underlying Hibernate persistence provider.
     *
     * @param exampleEntity enity to use as an example
     * @param excludedProperty array of excluded properties of the example
     * @return List<T> list of matching entities of type T
     */
    @SuppressWarnings("unchecked")
    public List<T> findByExample(T exampleEntity, String[] excludedProperty) {
        Criteria criteria = createCritiera();
        Example example = Example.create(exampleEntity);

        for (String exclude : excludedProperty)
            example.excludeProperty(exclude);

        criteria.add(example);
        return criteria.list();
    }

    /**
     * Returns a list of all entities matching the given Criterion.
     *
     * @param criterion criteria to match
     * @return List<T> list of matching entities of type T
     */
    @SuppressWarnings("unchecked")
    public List<T> findByCriteria(Criterion... criterion) {
        Criteria criteria = createCritiera();
        for (Criterion c : criterion)
            criteria.add(c);

        return criteria.list();
    }

    /**
     * Creates a Hibernate Criteria instance for the bound entity type T.
     *
     * This method requires an underlying Hibernate persistence provider.
     *
     * @return criteria
     */
    protected Criteria createCritiera() {
        return getSession().createCriteria(getEntityBeanType());
    }
}