mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-06-26 05:42:31 +00:00
Refactored. NB: This code is unsupported and illustrates non-anemic domain objects that do not leverage transparent persistence capabilities (I recommend you use transparent persistence capabilities where possible - I hope to check in different packages with new patterns in due course).
This commit is contained in:
parent
0581fc0759
commit
12c78791de
@ -52,5 +52,5 @@ public interface PersistableEntity {
|
||||
*
|
||||
* @return the persistence identity of this instance
|
||||
*/
|
||||
abstract Serializable getInternalId();
|
||||
public abstract Serializable getInternalId();
|
||||
}
|
||||
|
@ -15,13 +15,13 @@
|
||||
|
||||
package org.acegisecurity.domain.dao;
|
||||
|
||||
import org.acegisecurity.domain.PersistableEntity;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.acegisecurity.domain.PersistableEntity;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
|
||||
/**
|
||||
* Provides fundamental DAO capabilities for a single concrete {@link
|
||||
* PersistableEntity}, using JDK 1.5 generics.
|
||||
@ -44,9 +44,7 @@ import java.util.List;
|
||||
* be the sole entry point into the persistance layer of an application. The
|
||||
* persistence layer should only respond to requests from the services layer.
|
||||
* The services layer is where all transaction demarcation, security
|
||||
* authorization, casting to and from concrete {@link
|
||||
* org.acegisecurity.domain.PersistableEntity}s, workflow and business
|
||||
* logic should take place.
|
||||
* authorization, workflow and business logic should take place.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
@ -67,17 +65,15 @@ public interface Dao<E extends PersistableEntity> {
|
||||
* PersistableEntity#getInternalId()} value being ignored.
|
||||
*
|
||||
* @param value (without the identity property initialized)
|
||||
*
|
||||
* @return the value created (with the identity property initialised)
|
||||
*/
|
||||
public E create(E value);
|
||||
public void create(E value) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Delete an object.
|
||||
*
|
||||
* @param value the value to delete
|
||||
*/
|
||||
public void delete(E value);
|
||||
public void delete(E value) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Return all persistent instances, including subclasses.
|
||||
@ -85,7 +81,7 @@ public interface Dao<E extends PersistableEntity> {
|
||||
* @return all persistence instances (an empty <code>List</code> will be
|
||||
* returned if no matches are found)
|
||||
*/
|
||||
public List<E> findAll();
|
||||
public List<E> findAll() throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Find a <code>List</code> of <code>PersistableEntity</code>s, searched by
|
||||
@ -96,7 +92,7 @@ public interface Dao<E extends PersistableEntity> {
|
||||
* @return the values with those identifiers (an empty <code>List</code>
|
||||
* will be returned if no matches are found)
|
||||
*/
|
||||
public List<E> findId(Collection<Serializable> ids);
|
||||
public List<E> findId(Collection<Serializable> ids) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Load a persistent instance by its identifier, although some properties
|
||||
@ -108,19 +104,8 @@ public interface Dao<E extends PersistableEntity> {
|
||||
*
|
||||
* @return the request item, or <code>null</code> if not found
|
||||
*/
|
||||
public E readId(Serializable id);
|
||||
public E readId(Serializable id) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Loads a persistent instance by its identifier, along with any
|
||||
* lazy loaded properties associated with that instance.
|
||||
*
|
||||
* @param id the identifier of the persistent instance desired to be
|
||||
* retrieved
|
||||
*
|
||||
* @return the request item, or <code>null</code> if not found
|
||||
*/
|
||||
public E readPopulatedId(Serializable id);
|
||||
|
||||
/**
|
||||
* Find persistent instances with properties matching those of the passed
|
||||
* <code>PersistableEntity</code>.
|
||||
@ -146,36 +131,7 @@ public interface Dao<E extends PersistableEntity> {
|
||||
* <code>PaginatedList</code> is returned if no results match)
|
||||
*/
|
||||
public PaginatedList<E> scroll(E value, int firstElement,
|
||||
int maxElements, String orderByAsc);
|
||||
|
||||
/**
|
||||
* Find persistent instances with properties matching those of the passed
|
||||
* <code>PersistableEntity</code>, with a guarantee the returned results
|
||||
* will have each of the <code>value</code> class' immediate properties
|
||||
* initialized.
|
||||
*
|
||||
* <P>
|
||||
* Persistent instances are matched on the basis of query by example.
|
||||
* Properties whose value is <code>null</code>, empty
|
||||
* <code>String</code>s, and any <code>Collection</code>s are ignored in
|
||||
* the query by example evaluation.
|
||||
* </p>
|
||||
*
|
||||
* @param value parameters to filter on (the class of this object will
|
||||
* be added to the filter)
|
||||
* @param firstElement the first result (start at zero to obtain all
|
||||
* results)
|
||||
* @param maxElements the maximum number of results desired for this page
|
||||
* of the result set
|
||||
* @param orderByAsc the property name of the
|
||||
* <code>PersistableEntity</code> that should be used to order the
|
||||
* results
|
||||
*
|
||||
* @return the requested page of the result list (a properly formed
|
||||
* <code>PaginatedList</code> is returned if no results match)
|
||||
*/
|
||||
public PaginatedList<E> scrollPopulated(E value, int firstElement,
|
||||
int maxElements, String orderByAsc);
|
||||
int maxElements, String orderByAsc) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Find persistent instances with properties matching those of the passed
|
||||
@ -197,31 +153,7 @@ public interface Dao<E extends PersistableEntity> {
|
||||
* <code>PaginatedList</code> is returned if no results match)
|
||||
*/
|
||||
public PaginatedList<E> scrollWithSubclasses(E value, int firstElement,
|
||||
int maxElements, String orderByAsc);
|
||||
|
||||
/**
|
||||
* Find persistent instances with properties matching those of the passed
|
||||
* <code>PersistableEntity</code>, ignoring the class of the passed
|
||||
* <code>PersistableEntity</code> (useful if you pass a superclass, as you
|
||||
* want to find all subclass instances which match). Guarantees the returned
|
||||
* results will have each of the DAO's <code>supports</code> class' immediate
|
||||
* properties initialized.
|
||||
*
|
||||
* @param value parameters to filter on (the class of this object will
|
||||
* NOT be added to the filter)
|
||||
* @param firstElement the first result (start at zero to obtain all
|
||||
* results)
|
||||
* @param maxElements the maximum number of results desired for this page
|
||||
* of the result set
|
||||
* @param orderByAsc the property name of the
|
||||
* <code>PersistableEntity</code> that should be used to order the
|
||||
* results
|
||||
*
|
||||
* @return the requested page of the result list (a properly formed
|
||||
* <code>PaginatedList</code> is returned if no results match)
|
||||
*/
|
||||
public PaginatedList<E> scrollPopulatedWithSubclasses(E value, int firstElement,
|
||||
int maxElements, String orderByAsc);
|
||||
int maxElements, String orderByAsc) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Indicates whether the DAO instance provides persistence services for the
|
||||
@ -240,8 +172,6 @@ public interface Dao<E extends PersistableEntity> {
|
||||
*
|
||||
* @param value to update, with the <code>PersistableEntity</code> having a
|
||||
* non-<code>null</code> identifier
|
||||
*
|
||||
* @return the updated value
|
||||
*/
|
||||
public E update(E value);
|
||||
public void update(E value) throws DataAccessException;
|
||||
}
|
||||
|
@ -16,36 +16,26 @@
|
||||
package org.acegisecurity.domain.hibernate;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.acegisecurity.domain.PersistableEntity;
|
||||
import org.acegisecurity.domain.dao.Dao;
|
||||
import org.acegisecurity.domain.dao.DetachmentContextHolder;
|
||||
import org.acegisecurity.domain.dao.EvictionCapable;
|
||||
import org.acegisecurity.domain.dao.InitializationCapable;
|
||||
import org.acegisecurity.domain.dao.PaginatedList;
|
||||
import org.acegisecurity.domain.util.GenericsUtils;
|
||||
import org.acegisecurity.domain.validation.ValidationManager;
|
||||
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.EntityMode;
|
||||
import org.hibernate.FetchMode;
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.criterion.Expression;
|
||||
import org.hibernate.criterion.MatchMode;
|
||||
import org.hibernate.criterion.Order;
|
||||
import org.hibernate.metadata.ClassMetadata;
|
||||
import org.hibernate.type.Type;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.orm.hibernate3.HibernateCallback;
|
||||
import org.springframework.orm.hibernate3.HibernateTemplate;
|
||||
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.validation.BindException;
|
||||
|
||||
|
||||
/**
|
||||
@ -55,180 +45,65 @@ import org.springframework.validation.BindException;
|
||||
* @author Matthew Porter
|
||||
* @version $Id$
|
||||
*/
|
||||
public class DaoHibernate<E extends PersistableEntity> extends HibernateDaoSupport implements Dao<E>,
|
||||
EvictionCapable, InitializationCapable {
|
||||
public class DaoHibernate<E extends PersistableEntity> extends HibernateDaoSupport implements Dao<E> {
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
/** The class that this instance provides services for */
|
||||
private Class supportsClass;
|
||||
|
||||
/** Enables mutator methods to validate an object prior to persistence */
|
||||
private ValidationManager validationManager;
|
||||
|
||||
public DaoHibernate() {
|
||||
public DaoHibernate(SessionFactory sessionFactory) {
|
||||
Assert.notNull(sessionFactory, "Non-null Hibernate SessionFactory must be expressed as a constructor argument");
|
||||
super.setSessionFactory(sessionFactory);
|
||||
this.supportsClass = GenericsUtils.getGeneric(getClass());
|
||||
if (this.supportsClass == null) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("Could not determine the generics type - you will need to set manually");
|
||||
}
|
||||
}
|
||||
Assert.notNull(this.supportsClass, "Could not determine the generics type");
|
||||
}
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
/**
|
||||
* Obtains a <code>HibernateTemplate</code> that uses the appropriate <code>Session</code>
|
||||
* based on the value of {@link DetachmentContextHolder}.
|
||||
*
|
||||
* <p>Specifically, if <code>DetachmentContextHolder</code> requires detached instances,
|
||||
* the method will build a new <code>Session</code> (ignore the current thread-bound
|
||||
* <code>Session</code>) and use that new <code>Session</code> in the <code>HibernateTemplate</code>.
|
||||
* If <code>DetachmentContextHolder</code> is at its fault <code>false</code> value, the
|
||||
* returned <code>HibernateTemplate</code> will simply use the <code>Session</code> obtained
|
||||
* from the superclass, which is generally the same <code>Session</code> as used for the
|
||||
* transaction.
|
||||
*
|
||||
* @return the template, containing the correct <code>Session</code> based on the
|
||||
* <code>DetachmentContactHolder</code> request
|
||||
*/
|
||||
protected HibernateTemplate doGetHibernateTemplate() {
|
||||
if (DetachmentContextHolder.isForceReturnOfDetachedInstances()) {
|
||||
HibernateTemplate hibernateTemplate = new HibernateTemplate(getSessionFactory());
|
||||
hibernateTemplate.setAlwaysUseNewSession(true);
|
||||
return hibernateTemplate;
|
||||
} else {
|
||||
return super.getHibernateTemplate();
|
||||
}
|
||||
}
|
||||
|
||||
public void setSupportsClass(Class supportClass) {
|
||||
this.supportsClass = supportClass;
|
||||
}
|
||||
|
||||
public Class getSupportsClass() {
|
||||
return supportsClass;
|
||||
}
|
||||
|
||||
public ValidationManager getValidationManager() {
|
||||
return validationManager;
|
||||
}
|
||||
|
||||
public void setValidationManager(ValidationManager validationManager) {
|
||||
this.validationManager = validationManager;
|
||||
}
|
||||
|
||||
public E create(E value) {
|
||||
public void create(E value) {
|
||||
Assert.notNull(value);
|
||||
validate(value);
|
||||
doGetHibernateTemplate().save(value);
|
||||
|
||||
return readId(value.getInternalId());
|
||||
super.getHibernateTemplate().save(value);
|
||||
}
|
||||
|
||||
protected void validate(E value) throws DataIntegrityViolationException {
|
||||
try {
|
||||
validationManager.validate(value);
|
||||
} catch (BindException bindException) {
|
||||
throw new DataIntegrityViolationException("Entity state is invalid", bindException);
|
||||
}
|
||||
}
|
||||
|
||||
public void delete(E value) {
|
||||
Assert.notNull(value);
|
||||
validate(value);
|
||||
doGetHibernateTemplate().delete(value);
|
||||
super.getHibernateTemplate().delete(value);
|
||||
}
|
||||
|
||||
public void evict(PersistableEntity entity) {
|
||||
Assert.notNull(entity);
|
||||
doGetHibernateTemplate().evict(entity);
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<E> findAll() {
|
||||
return super.getHibernateTemplate().loadAll(supportsClass);
|
||||
}
|
||||
|
||||
public List<E> findAll() {
|
||||
return doGetHibernateTemplate().loadAll(supportsClass);
|
||||
}
|
||||
|
||||
public List<E> findId(Collection<Serializable> ids) {
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<E> findId(Collection<Serializable> ids) {
|
||||
Assert.notNull(ids, "Collection of IDs cannot be null");
|
||||
Assert.notEmpty(ids, "There must be some values in the Collection list");
|
||||
|
||||
return (List) doGetHibernateTemplate().execute(getFindByIdCallback(ids));
|
||||
return (List) super.getHibernateTemplate().execute(getFindByIdCallback(ids));
|
||||
}
|
||||
|
||||
private E readId(final Serializable id, final boolean populate) {
|
||||
@SuppressWarnings("unchecked")
|
||||
public E readId(Serializable id) {
|
||||
Assert.notNull(id);
|
||||
return (E) doGetHibernateTemplate().execute(new HibernateCallback() {
|
||||
public Object doInHibernate(Session session) throws HibernateException {
|
||||
E obj = (E) session.get(supportsClass, id);
|
||||
if (populate) {
|
||||
initializeAllZeroArgumentGetters(obj);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
}, true);
|
||||
return (E) getHibernateTemplate().load(supportsClass, id);
|
||||
}
|
||||
|
||||
public E readId(Serializable id) {
|
||||
Assert.notNull(id);
|
||||
return readId(id, false);
|
||||
}
|
||||
|
||||
public E readPopulatedId(Serializable id) {
|
||||
Assert.notNull(id);
|
||||
return readId(id, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Locates every <code>get*()</code> method against the passed entity
|
||||
* and calls it. This method does not nest its initialization beyond
|
||||
* the immediately passed entity.
|
||||
*
|
||||
* <p>For example, a Foo object might provide a getBar() method.
|
||||
* Passing the Foo instance to this method will guarantee getBar() is
|
||||
* available to the services layer. However, if getBar() returned a Bar
|
||||
* which in turn provided a getCar() method, there is NO GUARANTEE
|
||||
* the getCar() method will be initialized.
|
||||
*
|
||||
* @param entity for which its immediate getters should be initialized
|
||||
*/
|
||||
protected void initializeAllZeroArgumentGetters(E entity) {
|
||||
Method[] methods = entity.getClass().getMethods();
|
||||
for (int i = 0; i < methods.length; i++) {
|
||||
if (methods[i].getName().startsWith("get") && methods[i].getParameterTypes().length == 0) {
|
||||
try {
|
||||
Hibernate.initialize(methods[i].invoke(entity, new Object[] {}));
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PaginatedList<E> scroll(E value, int firstElement,
|
||||
@SuppressWarnings("unchecked")
|
||||
public PaginatedList<E> scroll(E value, int firstElement,
|
||||
int maxElements, String orderByAsc) {
|
||||
validateScrollMethod(value, firstElement, maxElements, orderByAsc);
|
||||
return (PaginatedList) doGetHibernateTemplate().execute(getFindByValueCallback(
|
||||
value.getClass(), false, value, firstElement, maxElements, Order.asc(orderByAsc)));
|
||||
return (PaginatedList) super.getHibernateTemplate().execute(getFindByValueCallback(
|
||||
value.getClass(), value, firstElement, maxElements, Order.asc(orderByAsc)));
|
||||
}
|
||||
|
||||
public PaginatedList<E> scrollWithSubclasses(E value, int firstElement,
|
||||
@SuppressWarnings("unchecked")
|
||||
public PaginatedList<E> scrollWithSubclasses(E value, int firstElement,
|
||||
int maxElements, String orderByAsc) {
|
||||
validateScrollMethod(value, firstElement, maxElements, orderByAsc);
|
||||
return (PaginatedList) doGetHibernateTemplate().execute(getFindByValueCallback(
|
||||
this.supportsClass, false, value, firstElement, maxElements, Order.asc(orderByAsc)));
|
||||
return (PaginatedList) super.getHibernateTemplate().execute(getFindByValueCallback(
|
||||
this.supportsClass, value, firstElement, maxElements, Order.asc(orderByAsc)));
|
||||
}
|
||||
|
||||
public PaginatedList<E> scrollPopulated(E value, int firstElement,
|
||||
int maxElements, String orderByAsc) {
|
||||
validateScrollMethod(value, firstElement, maxElements, orderByAsc);
|
||||
return (PaginatedList) doGetHibernateTemplate().execute(getFindByValueCallback(
|
||||
value.getClass(), true, value, firstElement, maxElements, Order.asc(orderByAsc)));
|
||||
}
|
||||
|
||||
public PaginatedList<E> scrollPopulatedWithSubclasses(E value, int firstElement,
|
||||
int maxElements, String orderByAsc) {
|
||||
validateScrollMethod(value, firstElement, maxElements, orderByAsc);
|
||||
return (PaginatedList) doGetHibernateTemplate().execute(getFindByValueCallback(
|
||||
this.supportsClass, true, value, firstElement, maxElements, Order.asc(orderByAsc)));
|
||||
}
|
||||
|
||||
private void validateScrollMethod(E value, int firstElement, int MaxElements, String orderByAsc) {
|
||||
Assert.notNull(value);
|
||||
@ -239,46 +114,14 @@ public class DaoHibernate<E extends PersistableEntity> extends HibernateDaoSuppo
|
||||
|
||||
public boolean supports(Class clazz) {
|
||||
Assert.notNull(clazz);
|
||||
|
||||
return this.supportsClass.equals(clazz);
|
||||
}
|
||||
|
||||
public E update(E value) {
|
||||
public void update(E value) {
|
||||
Assert.notNull(value);
|
||||
validate(value);
|
||||
doGetHibernateTemplate().update(value);
|
||||
|
||||
return readId(value.getInternalId());
|
||||
super.getHibernateTemplate().update(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom initialization behavior. Called by superclass.
|
||||
*
|
||||
* @throws Exception if initialization fails
|
||||
*/
|
||||
protected final void initDao() throws Exception {
|
||||
Assert.notNull(supportsClass, "supportClass is required");
|
||||
Assert.notNull(validationManager, "validationManager is required");
|
||||
Assert.isTrue(PersistableEntity.class.isAssignableFrom(supportsClass), "supportClass is not an implementation of PersistableEntity");
|
||||
initHibernateDao();
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows subclasses to provide custom initialization behaviour. Called
|
||||
* during {@link #initDao()}.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
protected void initHibernateDao() throws Exception {}
|
||||
|
||||
public void initialize(Object entity) {
|
||||
Hibernate.initialize(entity);
|
||||
}
|
||||
|
||||
public boolean isInitialized(Object entity) {
|
||||
return Hibernate.isInitialized(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a <code>HibernateCallback</code> that will load a list of
|
||||
* objects by a <code>Collection</code> of identities.
|
||||
@ -313,8 +156,6 @@ public class DaoHibernate<E extends PersistableEntity> extends HibernateDaoSuppo
|
||||
* match, otherwise find by exact match.
|
||||
*
|
||||
* @param whichClass the class (and subclasses) which results will be limited to including
|
||||
* @param initializeAllProperties indicates whether lazy initialized properties
|
||||
* should be initialized in the returned results
|
||||
* @param bean bean with the values of the parameters
|
||||
* @param firstElement the first result, numbered from 0
|
||||
* @param count the maximum number of results
|
||||
@ -322,15 +163,16 @@ public class DaoHibernate<E extends PersistableEntity> extends HibernateDaoSuppo
|
||||
*
|
||||
* @return a PaginatedList containing the requested objects
|
||||
*/
|
||||
private HibernateCallback getFindByValueCallback(final Class whichClass, final boolean initializeAllProperties, final Object bean,
|
||||
final int firstElement, final int count, final Order order) {
|
||||
private HibernateCallback getFindByValueCallback(final Class whichClass, final Object bean, final int firstElement, final int count, final Order order) {
|
||||
return new HibernateCallback() {
|
||||
public Object doInHibernate(Session session)
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object doInHibernate(Session session)
|
||||
throws HibernateException {
|
||||
Criteria criteria = session.createCriteria(whichClass);
|
||||
|
||||
criteria.addOrder(order);
|
||||
|
||||
int paramCount = 0;
|
||||
|
||||
StringBuffer queryString = new StringBuffer("from ").append(bean.getClass().getName()).append(" as queryTarget");
|
||||
|
||||
|
||||
ClassMetadata classMetadata = getSessionFactory()
|
||||
.getClassMetadata(bean
|
||||
.getClass());
|
||||
@ -344,12 +186,6 @@ public class DaoHibernate<E extends PersistableEntity> extends HibernateDaoSuppo
|
||||
/* for each persistent property of the bean */
|
||||
for (int i = 0; i < propertyNames.length; i++) {
|
||||
String name = propertyNames[i];
|
||||
|
||||
// Indicate preferred fetching here
|
||||
if (initializeAllProperties) {
|
||||
criteria.setFetchMode(name, FetchMode.JOIN);
|
||||
}
|
||||
|
||||
// TODO: Check if EntityMode.POJO appropriate
|
||||
Object value = classMetadata.getPropertyValue(bean, name, EntityMode.POJO);
|
||||
|
||||
@ -371,35 +207,47 @@ public class DaoHibernate<E extends PersistableEntity> extends HibernateDaoSuppo
|
||||
continue;
|
||||
}
|
||||
|
||||
Type type = classMetadata.getPropertyType(name);
|
||||
|
||||
if (name.equals("version")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (name.equals("lastUpdatedUsername") || name.equals("lastUpdatedDate")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (type.equals(Hibernate.STRING)) {
|
||||
Type type = classMetadata.getPropertyType(name);
|
||||
|
||||
if (type.equals(Hibernate.STRING)) {
|
||||
// if the property is mapped as String, find partial match
|
||||
criteria.add(Expression.ilike(name,
|
||||
value.toString(), MatchMode.ANYWHERE));
|
||||
if (paramCount == 0) {
|
||||
queryString.append(" where ");
|
||||
} else {
|
||||
queryString.append(" and ");
|
||||
}
|
||||
paramCount++;
|
||||
queryString.append("lower(queryTarget.").append(name).append(") like '%" + value.toString().toLowerCase() + "%'");
|
||||
} else {
|
||||
// find exact match
|
||||
criteria.add(Expression.eq(name, value));
|
||||
if (paramCount == 0) {
|
||||
queryString.append(" where ");
|
||||
} else {
|
||||
queryString.append(" and ");
|
||||
}
|
||||
paramCount++;
|
||||
queryString.append("queryTarget.").append(name).append(" = " + value);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO Use Criteria.count() when available in next Hibernate
|
||||
* versions
|
||||
*/
|
||||
int size = criteria.list().size();
|
||||
|
||||
List<E> list = criteria.setFirstResult(firstElement).setMaxResults(count).list();
|
||||
|
||||
return new PaginatedList<E>(list, firstElement, count, size);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(queryString.toString());
|
||||
}
|
||||
|
||||
// Determine number of rows
|
||||
org.hibernate.Query countQuery = session.createQuery("select count(*) " + queryString.toString());
|
||||
int size = ((Integer) countQuery.iterate().next()).intValue();
|
||||
|
||||
// Obtain requested page of query
|
||||
org.hibernate.Query query = session.createQuery(queryString.toString());
|
||||
query.setMaxResults(count);
|
||||
query.setFirstResult(firstElement);
|
||||
|
||||
return new PaginatedList(query.list(), firstElement, count, size);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
|
||||
import org.acegisecurity.domain.util.GenericsUtils;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.usertype.UserType;
|
||||
|
||||
@ -32,9 +33,11 @@ import org.hibernate.usertype.UserType;
|
||||
* @version $Id$
|
||||
*/
|
||||
public class EnumUserType<E extends Enum<E>> implements UserType {
|
||||
private Class<E> clazz = null;
|
||||
protected EnumUserType(Class<E> c) {
|
||||
this.clazz = c;
|
||||
private Class<E> clazz = null;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected EnumUserType() {
|
||||
this.clazz = GenericsUtils.getGeneric(getClass());
|
||||
}
|
||||
|
||||
private static final int[] SQL_TYPES = {Types.VARCHAR};
|
||||
|
@ -64,13 +64,4 @@ public abstract class AbstractPersistableEntity extends BusinessObject
|
||||
public int getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the version numbers.
|
||||
*
|
||||
* @param version the new version number to use
|
||||
*/
|
||||
public void setVersion(int version) {
|
||||
this.version = version;
|
||||
}
|
||||
}
|
||||
|
@ -51,7 +51,11 @@ public abstract class BusinessObject implements Serializable, Cloneable {
|
||||
* Swallow cloning.
|
||||
*
|
||||
* <p>
|
||||
* This method delegates to BeanUtils.cloneBean().
|
||||
* This method delegates to BeanUtils.cloneBean(). Please note that
|
||||
* this class uses serialization to achieve a clone, so this may
|
||||
* represent a performance issue in certain applications. In
|
||||
* such circumstances you should override this method and provide
|
||||
* alternative cloning logic.
|
||||
* </p>
|
||||
*
|
||||
* @return a clone of the current instance
|
||||
|
@ -17,6 +17,7 @@ package org.acegisecurity.domain.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
/**
|
||||
* A persistable entity that uses a <code>Integer</code> based identity.
|
||||
*
|
||||
@ -26,49 +27,22 @@ import java.io.Serializable;
|
||||
public abstract class PersistableEntityInteger extends AbstractPersistableEntity {
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
protected Integer id;
|
||||
private Integer id;
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
/**
|
||||
* DO NOT USE DIRECTLY.
|
||||
*
|
||||
* <p>
|
||||
* Typically only used by the persistence layer, but provided with public
|
||||
* visibility to not limit flexibility.
|
||||
* </p>
|
||||
*
|
||||
* @param id the new instance identity
|
||||
*/
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the persistence identity of this instance.
|
||||
*
|
||||
* <p>Marked as abstract to remind users to implement. They'll need to implement
|
||||
* so their annotations reflect the correct sequence name.
|
||||
*/
|
||||
public abstract Integer getId();
|
||||
|
||||
public Integer getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* DO NOT USE DIRECTLY.
|
||||
*
|
||||
* <p>
|
||||
* Use {@link #getId()} instead, as it provides the correct return type.
|
||||
* This method is only provided for use by the persistence layer and to
|
||||
* satisfy the {@link org.acegisecurity.domain.PersistableEntity}
|
||||
* interface contract.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Internally delegates to {@link #getId()}.
|
||||
* </p>
|
||||
*
|
||||
* @return the instance's identity
|
||||
* Required solely because Hibernate
|
||||
*/
|
||||
public Serializable getInternalId() {
|
||||
return this.getId();
|
||||
return this.id;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ package org.acegisecurity.domain.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
/**
|
||||
* A persistable entity that uses a <code>Long</code> based identity.
|
||||
*
|
||||
@ -26,49 +27,23 @@ import java.io.Serializable;
|
||||
public abstract class PersistableEntityLong extends AbstractPersistableEntity {
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
protected Long id;
|
||||
private Long id;
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
|
||||
/**
|
||||
* DO NOT USE DIRECTLY.
|
||||
*
|
||||
* <p>
|
||||
* Typically only used by the persistence layer, but provided with public
|
||||
* visibility to not limit flexibility.
|
||||
* </p>
|
||||
*
|
||||
* @param id the new instance identity
|
||||
*/
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the persistence identity of this instance.
|
||||
*/
|
||||
public Long getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* DO NOT USE DIRECTLY.
|
||||
*
|
||||
* <p>
|
||||
* Use {@link #getId()} instead, as it provides the correct return type.
|
||||
* This method is only provided for use by the persistence layer and to
|
||||
* satisfy the {@link org.acegisecurity.domain.PersistableEntity}
|
||||
* interface contract.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Internally delegates to {@link #getId()}.
|
||||
* </p>
|
||||
*
|
||||
* @return the instance's identity
|
||||
* Required solely because Hibernate
|
||||
*/
|
||||
public Serializable getInternalId() {
|
||||
return this.getId();
|
||||
return this.id;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ package org.acegisecurity.domain.service;
|
||||
|
||||
import org.acegisecurity.domain.PersistableEntity;
|
||||
import org.acegisecurity.domain.dao.PaginatedList;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@ -28,18 +29,16 @@ import java.util.List;
|
||||
* PersistableEntity}, using JDK 1.5 generics.
|
||||
*
|
||||
* <P>
|
||||
* This interface provides a remoting protocol compliant approach to accessing
|
||||
* services layer logic for a given application. A generics-based services
|
||||
* layer interface decreases development time because the basic CRUD and finder
|
||||
* operations can be specified in a typesafe fashion that reuses superclass
|
||||
* code.
|
||||
* A design decision was to rely on by-reference calling semantics typical of
|
||||
* recommended same-JVM (colocated) deployment environments. If you are using
|
||||
* remoting you may need to provide a remoting facade that returns the updated
|
||||
* object to the client.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* It is not envisioned that this interface will provide <b>all</b> services layer
|
||||
* functions. The significant value of a services layer is the value-add beyond
|
||||
* simply fronting the DAO or applying validation/binding logic that is better
|
||||
* situated in the domain object or its validator. The type of value-adds
|
||||
* simply fronting the DAO. The type of value-adds
|
||||
* expected to be provided by a services layer include incrementing business
|
||||
* identifiers (eg an invoice number); generating messages for logging/audit
|
||||
* purposes (thus such messages are at a business transaction level of granularity,
|
||||
@ -47,17 +46,9 @@ import java.util.List;
|
||||
* the message becomes unclear); updating related domain objects via
|
||||
* their respective services layer beans (eg an invoice services layer bean
|
||||
* would call the general journal services layer bean to create the accrual
|
||||
* accounting entries); making changes to a domain object that requires
|
||||
* logic that is unsuitable to put into a validator because it extends
|
||||
* beyond a single domain object instance or requires access to other persistent
|
||||
* entities (eg computing taxation appliable to an invoice based on a break-down
|
||||
* of each item on the order, its delivery destination, and the customer);
|
||||
* producing messages (eg notify another system the invoice was created or
|
||||
* email the customer via SMTP); provide a layer to locate transaction and
|
||||
* security configuration; expose a reasonably protocol-independent interface
|
||||
* to the application that can be used by a variety of web services and
|
||||
* client types; ensure any returned objects are eagerly loaded to a well-defined
|
||||
* interface contract etc.
|
||||
* accounting entries); producing messages (eg notify another system the invoice
|
||||
* was created or email the customer via SMTP); provide a layer to locate transaction
|
||||
* and security configuration etc.
|
||||
* </p>
|
||||
*
|
||||
* <P>
|
||||
@ -85,7 +76,7 @@ public interface ImmutableManager<E extends PersistableEntity> {
|
||||
* @return all persistence instances (an empty <code>List</code> will be
|
||||
* returned if no matches are found)
|
||||
*/
|
||||
public List<E> findAll();
|
||||
public List<E> findAll() throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Find a <code>List</code> of <code>PersistableEntity</code>s, searched by
|
||||
@ -96,7 +87,7 @@ public interface ImmutableManager<E extends PersistableEntity> {
|
||||
* @return the values with those identifiers (an empty <code>List</code>
|
||||
* will be returned if no matches are found)
|
||||
*/
|
||||
public List<E> findId(Collection<Serializable> ids);
|
||||
public List<E> findId(Collection<Serializable> ids) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Load a persistent instance by its identifier, although some properties
|
||||
@ -108,19 +99,8 @@ public interface ImmutableManager<E extends PersistableEntity> {
|
||||
*
|
||||
* @return the request item, or <code>null</code> if not found
|
||||
*/
|
||||
public E readId(Serializable id);
|
||||
public E readId(Serializable id) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Loads a persistent instance by its identifier, along with any
|
||||
* lazy loaded properties associated with that instance.
|
||||
*
|
||||
* @param id the identifier of the persistent instance desired to be
|
||||
* retrieved
|
||||
*
|
||||
* @return the request item, or <code>null</code> if not found
|
||||
*/
|
||||
public E readPopulatedId(Serializable id);
|
||||
|
||||
/**
|
||||
* Find persistent instances with properties matching those of the passed
|
||||
* <code>PersistableEntity</code>.
|
||||
@ -143,33 +123,7 @@ public interface ImmutableManager<E extends PersistableEntity> {
|
||||
* <code>PaginatedList</code> is returned if no results match)
|
||||
*/
|
||||
public PaginatedList<E> scroll(E value, int firstElement,
|
||||
int maxElements);
|
||||
|
||||
/**
|
||||
* Find persistent instances with properties matching those of the passed
|
||||
* <code>PersistableEntity</code>, with a guarantee the returned results
|
||||
* will have each of the <code>value</code> class' immediate properties
|
||||
* initialized.
|
||||
*
|
||||
* <P>
|
||||
* Persistent instances are matched on the basis of query by example.
|
||||
* Properties whose value is <code>null</code>, empty
|
||||
* <code>String</code>s, and any <code>Collection</code>s are ignored in
|
||||
* the query by example evaluation.
|
||||
* </p>
|
||||
*
|
||||
* @param value parameters to filter on (the class of this object will
|
||||
* be added to the filter)
|
||||
* @param firstElement the first result (start at zero to obtain all
|
||||
* results)
|
||||
* @param maxElements the maximum number of results desired for this page
|
||||
* of the result set
|
||||
*
|
||||
* @return the requested page of the result list (a properly formed
|
||||
* <code>PaginatedList</code> is returned if no results match)
|
||||
*/
|
||||
public PaginatedList<E> scrollPopulated(E value, int firstElement,
|
||||
int maxElements);
|
||||
int maxElements) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Find persistent instances with properties matching those of the passed
|
||||
@ -188,29 +142,8 @@ public interface ImmutableManager<E extends PersistableEntity> {
|
||||
* <code>PaginatedList</code> is returned if no results match)
|
||||
*/
|
||||
public PaginatedList<E> scrollWithSubclasses(E value, int firstElement,
|
||||
int maxElements);
|
||||
int maxElements) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Find persistent instances with properties matching those of the passed
|
||||
* <code>PersistableEntity</code>, ignoring the class of the passed
|
||||
* <code>PersistableEntity</code> (useful if you pass a superclass, as you
|
||||
* want to find all subclass instances which match). Guarantees the returned
|
||||
* results will have each of the DAO's <code>supports</code> class' immediate
|
||||
* properties initialized.
|
||||
*
|
||||
* @param value parameters to filter on (the class of this object will
|
||||
* NOT be added to the filter)
|
||||
* @param firstElement the first result (start at zero to obtain all
|
||||
* results)
|
||||
* @param maxElements the maximum number of results desired for this page
|
||||
* of the result set
|
||||
*
|
||||
* @return the requested page of the result list (a properly formed
|
||||
* <code>PaginatedList</code> is returned if no results match)
|
||||
*/
|
||||
public PaginatedList<E> scrollPopulatedWithSubclasses(E value, int firstElement,
|
||||
int maxElements);
|
||||
|
||||
/**
|
||||
* Indicates whether the DAO instance provides persistence services for the
|
||||
* specified class.
|
||||
|
@ -23,8 +23,6 @@ import org.acegisecurity.domain.PersistableEntity;
|
||||
import org.acegisecurity.domain.dao.Dao;
|
||||
import org.acegisecurity.domain.dao.PaginatedList;
|
||||
import org.acegisecurity.domain.util.GenericsUtils;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.context.support.ApplicationObjectSupport;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@ -34,39 +32,25 @@ import org.springframework.util.Assert;
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class ImmutableManagerImpl<E extends PersistableEntity> extends ApplicationObjectSupport implements ImmutableManager<E>, InitializingBean {
|
||||
public class ImmutableManagerImpl<E extends PersistableEntity> extends ApplicationObjectSupport implements ImmutableManager<E> {
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
/** The class that this instance provides services for */
|
||||
private Class supportsClass;
|
||||
private String beanName;
|
||||
|
||||
protected Dao<E> dao;
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public ImmutableManagerImpl() {
|
||||
public ImmutableManagerImpl(Dao<E> dao) {
|
||||
// work out what domain object we support
|
||||
this.supportsClass = GenericsUtils.getGeneric(getClass());
|
||||
if (supportsClass == null) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("Could not determine the generics type - you will need to set manually");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setSupportsClass(Class supportClass) {
|
||||
this.supportsClass = supportClass;
|
||||
}
|
||||
|
||||
public Class getSupportsClass() {
|
||||
return supportsClass;
|
||||
}
|
||||
|
||||
public Dao<E> getDao() {
|
||||
return dao;
|
||||
}
|
||||
|
||||
public void setDao(Dao<E> dao) {
|
||||
Assert.notNull(this.supportsClass, "Could not determine the generics type");
|
||||
Assert.isTrue(PersistableEntity.class.isAssignableFrom(supportsClass), "supportClass is not an implementation of PersistableEntity");
|
||||
|
||||
// store the DAO and check it also supports our domain object type
|
||||
Assert.notNull(dao, "Non-null DAO (that supports the same domain object class as this services layer) is required as a constructor argument");
|
||||
Assert.isTrue(dao.supports(supportsClass), "Dao '" + dao + "' does not support '" + supportsClass + "'");
|
||||
this.dao = dao;
|
||||
}
|
||||
|
||||
@ -76,22 +60,6 @@ public class ImmutableManagerImpl<E extends PersistableEntity> extends Applicati
|
||||
protected String getDefaultSortOrder() {
|
||||
return "id";
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides hook for custom subclasses to provide initialization behaviour
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
protected void doInitManager() throws Exception {}
|
||||
|
||||
public final void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(supportsClass, "supportClass is required");
|
||||
Assert.isTrue(PersistableEntity.class.isAssignableFrom(supportsClass),
|
||||
"supportClass is not an implementation of PersistableEntity");
|
||||
Assert.notNull(dao, "Dao is null");
|
||||
Assert.isTrue(dao.supports(supportsClass), "Dao '" + dao + "' does not support '" + supportsClass + "'");
|
||||
doInitManager();
|
||||
}
|
||||
|
||||
public List<E> findAll() {
|
||||
return dao.findAll();
|
||||
@ -108,11 +76,6 @@ public class ImmutableManagerImpl<E extends PersistableEntity> extends Applicati
|
||||
return dao.readId(id);
|
||||
}
|
||||
|
||||
public E readPopulatedId(Serializable id) {
|
||||
Assert.notNull(id);
|
||||
return dao.readPopulatedId(id);
|
||||
}
|
||||
|
||||
public PaginatedList<E> scroll(E value, int firstElement,
|
||||
int maxElements) {
|
||||
Assert.notNull(value);
|
||||
@ -121,13 +84,6 @@ public class ImmutableManagerImpl<E extends PersistableEntity> extends Applicati
|
||||
return dao.scroll(value, firstElement, maxElements, getDefaultSortOrder());
|
||||
}
|
||||
|
||||
public PaginatedList<E> scrollPopulated(E value, int firstElement, int maxElements) {
|
||||
Assert.notNull(value);
|
||||
Assert.isInstanceOf(this.supportsClass, value, "Can only scroll with values this manager supports");
|
||||
|
||||
return dao.scrollPopulated(value, firstElement, maxElements, getDefaultSortOrder());
|
||||
}
|
||||
|
||||
public PaginatedList<E> scrollWithSubclasses(E value, int firstElement,
|
||||
int maxElements) {
|
||||
Assert.notNull(value);
|
||||
@ -136,20 +92,8 @@ public class ImmutableManagerImpl<E extends PersistableEntity> extends Applicati
|
||||
return dao.scrollWithSubclasses(value, firstElement, maxElements, getDefaultSortOrder());
|
||||
}
|
||||
|
||||
public PaginatedList<E> scrollPopulatedWithSubclasses(E value, int firstElement, int maxElements) {
|
||||
Assert.notNull(value);
|
||||
Assert.isInstanceOf(this.supportsClass, value, "Can only scroll with values this manager supports");
|
||||
|
||||
return dao.scrollPopulatedWithSubclasses(value, firstElement, maxElements, getDefaultSortOrder());
|
||||
}
|
||||
|
||||
public boolean supports(Class clazz) {
|
||||
Assert.notNull(clazz);
|
||||
|
||||
return this.supportsClass.equals(clazz);
|
||||
}
|
||||
|
||||
public void setBeanName(String beanName) {
|
||||
this.beanName = beanName;
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ public class GenericsUtils {
|
||||
* @param clazz The class to introspect
|
||||
* @return the first generic declaration, or <code>null</code> if cannot be determined
|
||||
*/
|
||||
public static Class getGeneric(Class clazz) {
|
||||
public static Class getGeneric(Class clazz) {
|
||||
Type genType = clazz.getGenericSuperclass();
|
||||
|
||||
if (genType instanceof ParameterizedType) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user