package com.icentris.hibernate;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataRetrievalFailureException;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import java.util.*;
/**
* Created By: Scot Post van der Burg +
*
* Date: Oct 4, 2007
* Time: 1:52:34 PM
*/
public class BaseDao<T> extends HibernateDaoSupport implements IDao<T> {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class Fields
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
protected Class<? extends T> clazz;
private Log log = LogFactory.getLog(this.getClass());
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class Constructor(s)
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public BaseDao(Class<? extends T> clazz) {
this.clazz = clazz;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Accessors and Mutators
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class Methods
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public List<T> find(Map<String, Object> params) throws DataAccessException {
return _find(params, null);
}
public <S> List<S> findIds(Map<String, Object> params) throws DataAccessException {
List results = _find(params, new FindCriteriaSupplementor(){
public void supplementFindCriteria(Criteria c) {
c.setProjection(Projections.property("id"));
}
});
return (List<S>)results;
}
public List<T> findByExample( T example ) {
return getHibernateTemplate().findByExample(example);
}
public int getCount(Map<String, Object> params) throws DataAccessException{
List results = _find(params, new FindCriteriaSupplementor(){
public void supplementFindCriteria(Criteria c) {
c.setProjection(Projections.count("id"));
}
});
return (Integer)results.get(0);
}
protected List<T> _find(Map<String, Object> params, FindCriteriaSupplementor supplementor) throws DataAccessException{
params = params != null ? params : new HashMap<String, Object>();
List aliases = new ArrayList<String>();
Criteria c = getSession().createCriteria(clazz);
for(String attributeName : params.keySet()){
Object value = params.get(attributeName);
if(value != null){
if(value instanceof Collection){
c.add(Restrictions.in(attributeName, (Collection)value));
}
else if (attributeName.indexOf(".") > 0) {
// Nested property (Currently only supports one level)
String[] attrNames = attributeName.split("\\.");
if (!aliases.contains(attrNames[0])) {
c.createAlias(attrNames[0], attrNames[0]);
aliases.add(attrNames[0]);
}
if (value == null ) {
c.add( Restrictions.isNull( attributeName ));
} else if ( value instanceof String && ((String)value).endsWith( "%" )) {
c.add(Restrictions.ilike(attributeName, value));
} else {
c.add(Restrictions.eq(attributeName, value));
}
}
else{
if (value == null ) {
c.add( Restrictions.isNull( attributeName ));
} else if ( value instanceof String && ((String)value).endsWith( "%" )) {
c.add(Restrictions.ilike(attributeName, value));
} else {
c.add(Restrictions.eq(attributeName, value));
}
}
}
else{
c.add(Restrictions.isNull(attributeName));
}
}
if(supplementor != null){
supplementor.supplementFindCriteria(c);
}
return c.list();
}
public T create(T t) throws DataAccessException {
this.getHibernateTemplate().save( t );
return t;
}
public T save(T t) throws DataAccessException {
this.getHibernateTemplate().saveOrUpdate(t);
return t;
}
public T update(T t) throws DataAccessException {
this.getHibernateTemplate().update( t );
return t;
}
public int delete(Map<String, Object> params) throws DataAccessException {
params = params != null ? params : new HashMap<String, Object>();
Iterator<String> paramIter = params.keySet().iterator();
String whereExpression = paramIter.hasNext() ? " where %s" : "";
ArrayList<String> namedParams = new ArrayList<String>();
while(paramIter.hasNext()){
String param = paramIter.next();
Object value = params.get(param);
boolean isListValue = value instanceof Collection;
if(paramIter.hasNext()){
if(value != null){
whereExpression = String.format(whereExpression, String.format("%s %s and %s ", param, isListValue ? String.format(" in (%s)", ":" + param) : String.format(" = %s", ":" + param), "%s"));
namedParams.add(param);
}
else{
whereExpression = String.format(whereExpression, String.format("%s is null and %s ", param, "%s"));
}
}
else{
if(value != null){
whereExpression = String.format(whereExpression, String.format("%s %s ", param, isListValue ? String.format(" in (%s)", ":" + param) : String.format(" = %s", ":" + param), "%s"));
namedParams.add(param);
}
else{
whereExpression = String.format(whereExpression, String.format("%s is null ", param));
}
}
}
String deleteSql = String.format("delete from %s %s",
(clazz.getName() == null?clazz.getSimpleName():clazz.getName())
, whereExpression);
Query q = getSession().createQuery(deleteSql);
Iterator valueIter = params.values().iterator();
int i = 0;
while(valueIter.hasNext()){
Object value = valueIter.next();
if(value != null){
if(value instanceof Collection){
q.setParameterList(namedParams.get(i++), (Collection)value);
}
else{
q.setParameter(namedParams.get(i++), value);
}
}
}
int results = q.executeUpdate();
flush();
if(log.isDebugEnabled()){
log.debug("Successfully deleted " + results + String.format(clazz.getSimpleName()));
}
return results;
}
public void flush() throws DataAccessException {
try {
getSession().flush();
}
catch (HibernateException e) {
throw convertHibernateAccessException(e);
}
}
public void evict(T t) throws DataAccessException {
T result = null;
try {
getSession().evict(t);
}
catch (HibernateException e) {
throw convertHibernateAccessException(e);
}
}
public T merge(T t) throws DataAccessException {
return (T)getSession().merge(t);
}
public T findById(Object id) throws DataAccessException {
Map<String,Object> params = new HashMap<String,Object>();
params.put( "id", id );
List<T> results = _find( params, null );
return _uniqueResult( results, "id [" + id + "]" );
}
protected T _uniqueResult( List<T> results, String uniqueReason ) {
if ( results == null || results.size() == 0 ) {
return null;
}
if ( results.size() > 1 ) {
throw new DataRetrievalFailureException( "Multiple instances found with " + uniqueReason );
}
return results.get(0);
}
}