
org.trails.hibernate.HibernatePersistenceServiceImpl Maven / Gradle / Ivy
/*
* Copyright 2004 Chris Nelson
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
package org.trails.hibernate;
import java.io.Serializable;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import ognl.Ognl;
import ognl.OgnlException;
import org.hibernate.Criteria;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.Session;
import org.hibernate.TransientObjectException;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Expression;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.metadata.ClassMetadata;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.transaction.annotation.Transactional;
import org.trails.component.Utils;
import org.trails.descriptor.CollectionDescriptor;
import org.trails.descriptor.DescriptorService;
import org.trails.descriptor.IClassDescriptor;
import org.trails.descriptor.IPropertyDescriptor;
import org.trails.persistence.HibernatePersistenceService;
import org.trails.persistence.PersistenceException;
import org.trails.validation.ValidationException;
public class HibernatePersistenceServiceImpl extends HibernateDaoSupport implements
HibernatePersistenceService, ApplicationContextAware
{
ApplicationContext appContext = null;
private DescriptorService _descriptorService = null;
/**
* We need this because cylcic reference between HibernatePersistenceServiceImpl and TrailsDescriptorService
*/
public DescriptorService getDescriptorService()
{
if (_descriptorService == null)
{
_descriptorService = (DescriptorService) appContext.getBean("descriptorService");
}
return _descriptorService;
}
@Transactional
public T getInstance(final Class type, DetachedCriteria detachedCriteria) {
final DetachedCriteria criteria = alterCriteria(type, detachedCriteria);
return (T) getHibernateTemplate().execute(new HibernateCallback()
{
public Object doInHibernate(Session session) throws HibernateException, SQLException
{
return criteria.getExecutableCriteria(session).uniqueResult();
}
});
}
/**
* (non-Javadoc)
*
* @see org.trails.persistence.PersistenceService#getInstance(Class,Serializable)
*/
@Transactional
public T getInstance(final Class type, final Serializable id)
{
DetachedCriteria criteria = DetachedCriteria.forClass(Utils.checkForCGLIB(type)).add(Expression.idEq(id));
return getInstance(type, criteria);
}
public T loadInstance(final Class type, Serializable id)
{
return (T) getHibernateTemplate().load(type, id);
}
public List find(String queryString) {
return getHibernateTemplate().find(queryString);
}
public List find(String queryString, Object value) {
return getHibernateTemplate().find(queryString, value);
}
public List find(String queryString, Object[] values) {
return getHibernateTemplate().find(queryString, values);
}
/*
* (non-Javadoc)
*
* @see org.blah.service.IPersistenceService#getAllInstances(java.lang.Class)
*/
@Transactional
public List getAllInstances(final Class type)
{
DetachedCriteria criteria = DetachedCriteria.forClass(Utils.checkForCGLIB(type));
return getInstances(type, criteria);
}
public List getInstances(final Class type, int startIndex, int maxResults)
{
return getInstances(type, DetachedCriteria.forClass(type), startIndex, maxResults);
}
/*
* (non-Javadoc)
*
* @see org.blah.service.IPersistenceService#save(java.lang.Object)
*/
@Transactional
public T save(T instance) throws ValidationException
{
try
{
IClassDescriptor iClassDescriptor = getDescriptorService().getClassDescriptor(instance.getClass());
/* check isTransient to avoid merging on entities not persisted yet. TRAILS-33 */
if (!iClassDescriptor.getHasCyclicRelationships() || isTransient(instance, iClassDescriptor))
{
getHibernateTemplate().saveOrUpdate(instance);
} else
{
instance = (T) getHibernateTemplate().merge(instance);
}
return instance;
}
catch (DataAccessException dex)
{
throw new PersistenceException(dex);
}
}
@Transactional
public void removeAll(Collection collection)
{
getHibernateTemplate().deleteAll(collection);
}
@Transactional
public void remove(Object instance)
{
// merge first to avoid NonUniqueObjectException
getHibernateTemplate().delete(getHibernateTemplate().merge(instance));
}
@Transactional
public List getInstances(Class type, DetachedCriteria criteria) {
criteria = alterCriteria(type, criteria);
criteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
return getHibernateTemplate().findByCriteria(criteria);
}
public List getAllTypes()
{
ArrayList allTypes = new ArrayList();
for (Object classMetadata : getSessionFactory().getAllClassMetadata().values())
{
allTypes.add(((ClassMetadata) classMetadata).getMappedClass(EntityMode.POJO));
}
return allTypes;
}
@Transactional
public void reattach(Object model)
{
getSession().lock(model, LockMode.NONE);
}
/**
* (non-Javadoc)
*
* @see org.trails.persistence.PersistenceService#getInstance(Class)
*/
@Transactional
public T getInstance(final Class type)
{
return (T) getInstance(type, DetachedCriteria.forClass(type));
}
public Serializable getIdentifier(final Object data, final IClassDescriptor classDescriptor)
{
try
{
/** This is only until I figure out where are the Callbacks persisting its properties **/
return (Serializable) Ognl.getValue(classDescriptor.getIdentifierDescriptor().getName(), data);
} catch (OgnlException e)
{
return null;
}
}
private Serializable getIdentifier(final Object data)
{
return (Serializable) getHibernateTemplate().execute(new HibernateCallback()
{
public Object doInHibernate(Session session) throws HibernateException, SQLException
{
return session.getIdentifier(data);
}
});
}
public boolean isTransient(Object data, IClassDescriptor classDescriptor)
{
try
{
return getIdentifier(data, classDescriptor) == null;
} catch (TransientObjectException e)
{
return true;
}
}
@Transactional
public List getInstances(final Object example, final IClassDescriptor classDescriptor)
{
return (List) getHibernateTemplate().execute(new HibernateCallback()
{
public Object doInHibernate(Session session) throws HibernateException, SQLException
{
//create Criteria instance
DetachedCriteria searchCriteria = DetachedCriteria.forClass(Utils.checkForCGLIB(example.getClass()));
searchCriteria = alterCriteria(example.getClass(), searchCriteria);
//loop over the example object's PropertyDescriptors
for (IPropertyDescriptor propertyDescriptor : classDescriptor.getPropertyDescriptors())
{
//only add a Criterion to the Criteria instance if this property is searchable
if (propertyDescriptor.isSearchable())
{
String propertyName = propertyDescriptor.getName();
Class propertyClass = propertyDescriptor.getPropertyType();
Object value = null;
try
{
value = Ognl.getValue(propertyName, example);
} catch (OgnlException e)
{ /* do nothing! */ }
//only add a Criterion to the Criteria instance if the value for this property is non-null
if (value != null)
{
if (String.class.isAssignableFrom(propertyClass) && ((String) value).length() > 0)
{
searchCriteria
.add(Restrictions.like(propertyName, value.toString(), MatchMode.ANYWHERE));
}
/**
* 'one'-end of many-to-one, one-to-one
*
* Just match the identifier
*/
else if (propertyDescriptor.isObjectReference())
{
Serializable identifierValue = getIdentifier(value,
getDescriptorService().getClassDescriptor(propertyDescriptor.getBeanType()));
searchCriteria.createCriteria(propertyName).add(Restrictions.idEq(identifierValue));
} else if (propertyClass.isPrimitive())
{
//primitive types: ignore zeroes in case of numeric types, ignore booleans anyway (TODO come up with something...)
if (!propertyClass.equals(boolean.class) && ((Number) value).longValue() != 0)
{
searchCriteria.add(Restrictions.eq(propertyName, value));
}
} else if (propertyDescriptor.isCollection())
{
//one-to-many or many-to-many
CollectionDescriptor collectionDescriptor =
(CollectionDescriptor) propertyDescriptor;
IClassDescriptor classDescriptor = getDescriptorService().getClassDescriptor(collectionDescriptor.getElementType());
String identifierName = classDescriptor.getIdentifierDescriptor().getName();
Collection identifierValues = new ArrayList();
Collection associatedItems = (Collection) value;
if (associatedItems != null && associatedItems.size() > 0)
{
for (Object o : associatedItems)
{
identifierValues.add(getIdentifier(o, classDescriptor));
}
//add a 'value IN collection' restriction
searchCriteria.createCriteria(propertyName)
.add(Restrictions.in(identifierName, identifierValues));
}
}
}
}
}
searchCriteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
return searchCriteria.getExecutableCriteria(session).list();
}
}, true);
}
public void setApplicationContext(ApplicationContext arg0) throws BeansException
{
this.appContext = arg0;
}
public int count(Class type, DetachedCriteria detachedCriteria)
{
// todo hacking useNative is a result of SPR-2499 and will be removed soon
boolean useNative = getHibernateTemplate().isExposeNativeSession();
getHibernateTemplate().setExposeNativeSession(true);
detachedCriteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
final DetachedCriteria criteria = alterCriteria(type, detachedCriteria);
Integer result = (Integer) getHibernateTemplate().execute(new HibernateCallback()
{
public Object doInHibernate(Session session) throws HibernateException, SQLException
{
Criteria executableCriteria =
criteria.getExecutableCriteria(session).setProjection(Projections.rowCount());
return executableCriteria.uniqueResult();
}
});
getHibernateTemplate().setExposeNativeSession(useNative);
return result;
}
public List getInstances(Class type, final DetachedCriteria detachedCriteria, final int startIndex, final int maxResults)
{
return getInstances(alterCriteria(type, detachedCriteria), startIndex, maxResults);
}
public List getInstances(final DetachedCriteria detachedCriteria, final int startIndex, final int maxResults)
{
detachedCriteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
// todo hacking useNative is a result of SPR-2499 and will be removed soon
boolean useNative = getHibernateTemplate().isExposeNativeSession();
getHibernateTemplate().setExposeNativeSession(true);
List result = (List) getHibernateTemplate().execute(new HibernateCallback()
{
public Object doInHibernate(Session session) throws HibernateException, SQLException
{
Criteria executableCriteria = detachedCriteria.getExecutableCriteria(session);
if (startIndex >= 0)
{
executableCriteria.setFirstResult(startIndex);
}
if (maxResults > 0)
{
executableCriteria.setMaxResults(maxResults);
}
return executableCriteria.list();
}
});
getHibernateTemplate().setExposeNativeSession(useNative);
return result;
}
/**
* This hook allows subclasses to modify the query criteria, such as for security
*
* @param detachedCriteria The original Criteria query
* @return The modified Criteria query for execution
*/
protected DetachedCriteria alterCriteria(Class type, DetachedCriteria detachedCriteria)
{
return detachedCriteria;
}
/**
* @see org.trails.persistence.HibernatePersistenceService#saveOrUpdate(java.lang.Object)
*/
@Transactional
public T merge(T instance)
{
try
{
return (T) getHibernateTemplate().merge(instance);
}
catch (DataAccessException dex)
{
throw new PersistenceException(dex);
}
}
/**
* @see org.trails.persistence.HibernatePersistenceService#saveOrUpdate(java.lang.Object)
*/
@Transactional
public T saveOrUpdate(T instance) throws ValidationException
{
try
{
getHibernateTemplate().saveOrUpdate(instance);
return instance;
}
catch (DataAccessException dex)
{
throw new PersistenceException(dex);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy