package com.walters.sms;
import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.persistence.EntityManager;
import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.EntityMode;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.metadata.ClassMetadata;
import org.hibernate.type.Type;
import com.walters.common.args.CheckArg;
import com.walters.sms.domain.Persistable;
/**
* A supertype data access object (DAO) class providing persistence and searching support for
* persistent objects.
*/
public abstract class PersistenceService implements IPersistenceService
{
private static Logger logger = Logger.getLogger(PersistenceService.class);
@SuppressWarnings("unchecked")
public <T extends Persistable> T save(Persistable obj)
{
CheckArg.isNotNull(obj, "obj");
try
{
begin();
if (CheckArg.isNull(obj.getId()))
{
getSession().persist(obj);
}
else
{
obj = (Persistable) getSession().merge(obj);
}
commit();
}
catch (final HibernateException ex)
{
rollback();
throw new DataAccessException(ex);
}
finally
{
close();
}
return (T) obj;
}
@SuppressWarnings("unchecked")
public <T extends Persistable> T merge(Persistable obj)
{
CheckArg.isNotNull(obj, "obj");
try
{
begin();
obj = (Persistable) getSession().merge(obj);
commit();
}
catch (final HibernateException ex)
{
rollback();
throw new DataAccessException(ex);
}
finally
{
close();
}
return (T) obj;
}
@Override
public void delete(final Persistable obj) throws DataAccessException
{
CheckArg.isNotNull(obj, "object");
try
{
begin();
getSession().delete(obj);
commit();
}
catch (final HibernateException ex)
{
rollback();
throw new DataAccessException(ex);
}
finally
{
close();
}
}
public int deleteAll(@SuppressWarnings("rawtypes") final Class objClass) throws DataAccessException
{
CheckArg.isNotNull(objClass, "clazz");
int rowCount = 0;
try
{
begin();
final Query query = getSession().createQuery("delete " + objClass.getName());
rowCount = query.executeUpdate();
commit();
}
catch (final HibernateException ex)
{
rollback();
throw new DataAccessException(ex);
}
finally
{
close();
}
return rowCount;
}
@Override
public Persistable findById(@SuppressWarnings("rawtypes") final Class objClass, final Serializable id) throws DataAccessException
{
CheckArg.isNotNull(objClass, "objectClass");
CheckArg.isNotNull(id, "id");
Persistable obj = null;
try
{
begin();
obj = (Persistable) getSession().load(objClass, id);
commit();
}
catch (final HibernateException ex)
{
rollback();
throw new DataAccessException(ex);
}
finally
{
close();
}
return obj;
}
@SuppressWarnings("unchecked")
public List<?> findAll(@SuppressWarnings("rawtypes") final Class objClass) throws DataAccessException
{
CheckArg.isNotNull(objClass, "objClass");
List<Persistable> resultList = Collections.emptyList();
try
{
begin();
final Criteria criteria = getSession().createCriteria(objClass);
resultList = criteria.list();
commit();
}
catch (final HibernateException ex)
{
rollback();
throw new DataAccessException(ex);
}
finally
{
close();
}
return resultList;
}
@Override
public int count(@SuppressWarnings("rawtypes") final Class objClass) throws DataAccessException
{
CheckArg.isNotNull(objClass, "objClass");
int count = 0;
try
{
begin();
final Criteria criteria = getSession().createCriteria(objClass);
criteria.setProjection(Projections.rowCount());
count = ((Integer) criteria.list().get(0)).intValue();
commit();
}
catch (final HibernateException ex)
{
rollback();
throw new DataAccessException(ex);
}
finally
{
close();
}
return count;
}
protected int deleteWithNamedQuery(
final String namedQueryName,
final String property,
final Object value)
throws DataAccessException
{
CheckArg.isNotNull(namedQueryName, "query");
CheckArg.isNotNull(property, "property");
CheckArg.isNotNull(value, "value");
int rowCount = 0;
try
{
begin();
final Query query = getSession().getNamedQuery(namedQueryName);
query.setParameter(property, value);
rowCount = query.executeUpdate();
commit();
}
catch (final HibernateException ex)
{
rollback();
throw new DataAccessException(ex);
}
finally
{
close();
}
return rowCount;
}
protected int deleteAllWithNamedQuery(final String namedQueryName) throws DataAccessException
{
CheckArg.isNotNull(namedQueryName, "query");
int rowCount = 0;
try
{
begin();
final Query query = getSession().getNamedQuery(namedQueryName);
rowCount = query.executeUpdate();
commit();
}
catch (HibernateException ex)
{
rollback();
throw new DataAccessException(ex);
}
finally
{
close();
}
return rowCount;
}
/**
* @param namedQueryName
* @param property
* @param value
* @return
* @throws DataAccessException
*/
protected Object findWithNamedQuery(final String namedQueryName, final String property, final Object value)
throws DataAccessException
{
final List<?> list = findWithNamedQuery(namedQueryName, QueryParameter.with(property, value).parameters());
return (!list.isEmpty()) ? list.get(0) : null;
}
/**
* @param namedQueryName
* @param parameters
* @return
* @throws DataAccessException
*/
protected List<?> findWithNamedQuery(final String namedQueryName, final Map<String, Object> parameters)
throws DataAccessException
{
return findWithNamedQuery(namedQueryName, parameters, 0);
}
protected List<?> findWithNamedQuery(final String namedQueryName) throws DataAccessException
{
return findWithNamedQuery(namedQueryName, new HashMap<String, Object>());
}
/**
* @param namedQueryName
* @param parameters
* @param resultLimit
* @return
* @throws DataAccessException
*/
protected List<?> findWithNamedQuery(
final String namedQueryName,
final Map<String, Object> parameters,
final int resultLimit)
throws DataAccessException
{
CheckArg.isNotNull(namedQueryName, "query");
CheckArg.isNotNull(parameters, "parameters");
List<?> resultList = Collections.emptyList();
try
{
begin();
final Set<Entry<String, Object>> entries = parameters.entrySet();
final Query query = getSession().getNamedQuery(namedQueryName);
if (resultLimit > 0)
{
query.setMaxResults(resultLimit);
}
for (final Entry<String, Object> entry : entries)
{
query.setParameter(entry.getKey(), entry.getValue());
}
resultList = query.list();
commit();
}
catch (final HibernateException ex)
{
rollback();
throw new DataAccessException(ex);
}
finally
{
close();
}
return resultList;
}
@SuppressWarnings("unchecked")
protected <T> T findByPropertyValue(final String property, final Object value, @SuppressWarnings("rawtypes") final Class objClass)
throws DataAccessException
{
CheckArg.isNotNull(property, "property");
CheckArg.isNotNull(value, "value");
CheckArg.isNotNull(objClass, "class");
Object obj = null;
try
{
begin();
final Criteria criteria = getSession().createCriteria(objClass);
criteria.add(Restrictions.eq(property, value));
obj = criteria.uniqueResult();
commit();
}
catch (final HibernateException ex)
{
rollback();
throw new DataAccessException(ex);
}
finally
{
close();
}
return (T) obj;
}
@SuppressWarnings("unchecked")
protected <T> T findByCriteria(final Class<T> objClass, final Map<String, Object> parameters)
{
CheckArg.isNotNull(objClass, "objClass");
CheckArg.isNotNull(parameters, "parameters");
Object obj = null;
try
{
begin();
final Criteria criteria = getSession().createCriteria(objClass);
final Set<Entry<String, Object>> entries = parameters.entrySet();
for (final Entry<String, Object> entry : entries)
{
criteria.add(Restrictions.eq(entry.getKey(), entry.getValue()));
}
obj = (T) criteria.uniqueResult();
commit();
}
catch (final HibernateException ex)
{
rollback();
throw new DataAccessException(ex);
}
finally
{
close();
}
return (T) obj;
}
public int countByProperty(@SuppressWarnings("rawtypes") final Class objClass, final String property, final String value) throws DataAccessException
{
CheckArg.isNotNull(objClass, "objClass");
CheckArg.isNotNull(property, "property");
CheckArg.isNotNull(value, "value");
int count = 0;
try
{
begin();
final Criteria criteria = getSession().createCriteria(objClass);
criteria.add(Restrictions.eq(property, value));
criteria.setProjection(Projections.rowCount());
count = ((Integer) criteria.list().get(0)).intValue();
commit();
}
catch (final HibernateException ex)
{
rollback();
throw new DataAccessException(ex);
}
finally
{
close();
}
return count;
}
protected void initialize(final Object obj) throws DataAccessException
{
if (obj == null)
{
return;
}
try
{
final Class<?> objClass = Hibernate.getClass(obj);
if (!Hibernate.isInitialized(obj))
{
logger.debug("Force initialization of " + objClass.getName());
}
Hibernate.initialize(obj);
final ClassMetadata classMetadata = getSessionFactory().getClassMetadata(objClass);
if (classMetadata == null)
{
return;
}
for (int index = 0, size = classMetadata.getPropertyNames().length; index < size; index++)
{
final String propertyName = classMetadata.getPropertyNames()[index];
final Type type = classMetadata.getPropertyType(propertyName);
if (type.isEntityType())
{
final Object propertyValue = classMetadata.getPropertyValue(obj, propertyName, EntityMode.POJO);
if (!Hibernate.isInitialized(propertyValue))
{
initialize(propertyValue);
}
}
else if (type.isCollectionType())
{
final Collection<?> collection = (Collection<?>) classMetadata.getPropertyValue(
obj,
propertyName,
EntityMode.POJO);
Hibernate.initialize(collection);
for (Object collectionItem : collection)
{
initialize(collectionItem);
}
}
}
}
catch (final Exception ex)
{
throw new DataAccessException(ex);
}
}
protected void begin()
{
EntityManagerHelper.beginTransaction();
}
protected void commit()
{
EntityManagerHelper.commitTransaction();
}
protected void rollback()
{
try
{
final Transaction tx = getSession().getTransaction();
if (tx != null && tx.isActive())
{
tx.rollback();
}
}
catch (final HibernateException ex)
{
logger.warn("Couldn't rollbackTransaction Transaction", ex);
}
}
/**
* Access the same {@link EntityManager} instant throughout the lifetime of an application thread.
*
* @return Thread-safe EntityManager.
*/
protected EntityManager getEntityManager()
{
return EntityManagerHelper.getEntityManager();
}
protected void close()
{
try
{
EntityManagerHelper.closeEntityManager();
}
catch (final HibernateException ex)
{
logger.warn("Couldn't close entityManager", ex);
}
}
/**
* EntityManager#getDelegate() is not portable, i.e have different behaviour
* depending on the AS.
*
* @return Session
*/
protected Session getSession()
{
Session session = null;
final Object delegate = getEntityManager().getDelegate();
if (delegate instanceof org.hibernate.ejb.HibernateEntityManager)
{
session = ((org.hibernate.ejb.HibernateEntityManager) delegate).getSession();
}
else
{
session = (org.hibernate.Session) delegate;
}
return CheckArg.getNotNull(session, "session");
}
protected SessionFactory getSessionFactory()
{
return CheckArg.getNotNull(getSession().getSessionFactory(), "sessionFactory");
}
}