// Copyright 2007-2008 Thiago H. de Paula Figueiredo
//
// 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 br.com.arsmachina.dao.hibernate;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.SessionFactory;
import org.hibernate.classic.Session;
import org.hibernate.criterion.Example;
import org.hibernate.metadata.ClassMetadata;
import br.com.arsmachina.dao.DAO;
import br.com.arsmachina.dao.SortCriterion;
/**
* {@link AbstractDAO} implementation using Hibernate. All methods use {@link #getSession()} to get
* a {@link Session}. All methods delegate its calls to an internal {@link ReadableDAOImpl} or
* {@link WriteableDAOImpl} instance.
*
* @author Thiago H. de Paula Figueiredo
* @param <T> the entity class related to this DAO.
* @param <K> the type of the field that represents the entity class' primary key.
*/
public class GenericDAOImpl<T, K extends Serializable> implements DAO<T, K> {
final private InternalReadableDAOImpl readableDAO;
final private InternalWriteableDAOImpl writeableDAO;
/**
* Single public constructor.
*
* @param sessionFactory a {@link SessionFactory}. It cannot be null.
*/
@SuppressWarnings("unchecked")
public GenericDAOImpl(SessionFactory sessionFactory) {
if (sessionFactory == null) {
throw new IllegalArgumentException("Parameter sessionFactory cannot be null");
}
final Type genericSuperclass = getClass().getGenericSuperclass();
final ParameterizedType parameterizedType = ((ParameterizedType) genericSuperclass);
Class clasz = (Class<T>) parameterizedType.getActualTypeArguments()[0];
readableDAO = new InternalReadableDAOImpl(clasz, sessionFactory);
writeableDAO = new InternalWriteableDAOImpl(clasz, sessionFactory);
}
/**
* Constructor made specifically for {@link ConcreteDAOImpl}. It shouldn't be used in
* any other class.
*
* @param clasz the entity class. It cannot be null.
* @param sessionFactory a {@link SessionFactory}. It cannot be null.
*/
GenericDAOImpl(Class<T> clasz, SessionFactory sessionFactory) {
if (clasz == null) {
throw new IllegalArgumentException("Parameter clasz cannot be null");
}
if (sessionFactory == null) {
throw new IllegalArgumentException("Parameter sessionFactory cannot be null");
}
readableDAO = new InternalReadableDAOImpl(clasz, sessionFactory);
writeableDAO = new InternalWriteableDAOImpl(clasz, sessionFactory);
}
public int countAll() {
return readableDAO.countAll();
}
public List<T> findAll() {
return readableDAO.findAll();
}
public List<T> findAll(int firstResult, int maximumResults, SortCriterion... sortingConstraints) {
return readableDAO.findAll(firstResult, maximumResults, sortingConstraints);
}
public List<T> findByExample(T example) {
return readableDAO.findByExample(example);
}
public T findById(K id) {
return readableDAO.findById(id);
}
public List<T> findByIds(K... ids) {
return readableDAO.findByIds(ids);
}
public void refresh(T object) {
readableDAO.refresh(object);
}
public void delete(T object) {
writeableDAO.delete(object);
}
public void delete(K id) {
writeableDAO.delete(id);
}
public void evict(T object) {
writeableDAO.evict(object);
}
public boolean isPersistent(T object) {
return writeableDAO.isPersistent(object);
}
public void save(T object) {
writeableDAO.save(object);
}
public T update(T object) {
return writeableDAO.update(object);
}
public T reattach(T object) {
return readableDAO.reattach(object);
}
public SortCriterion[] getDefaultSortCriteria() {
return readableDAO.getDefaultSortCriteria();
}
/**
* Invokes <code>readableDAO.addSortCriteria()<code>.
* @param criteria
* @see br.com.arsmachina.dao.hibernate.ReadableDAOImpl#addSortCriteria(org.hibernate.Criteria)
*/
protected void addSortCriteria(Criteria criteria) {
readableDAO.addSortCriteria(criteria);
}
/**
* Invokes <code>delegate.addSortCriteria()<code>.
* @param criteria
* @param sortCriteria
* @see br.com.arsmachina.dao.hibernate.ReadableDAOImpl#addSortCriteria(org.hibernate.Criteria, br.com.arsmachina.dao.SortCriterion[])
*/
public final void addSortCriteria(Criteria criteria, SortCriterion... sortCriteria) {
readableDAO.addSortCriteria(criteria, sortCriteria);
}
/**
* Invokes <code>readableDAO.createCriteria()<code>.
* @return
* @see br.com.arsmachina.dao.hibernate.ReadableDAOImpl#createCriteria()
*/
protected Criteria createCriteria() {
return readableDAO.createCriteria();
}
/**
* Invokes <code>delegate.createCriteria()<code>.
* @param sortCriteria
* @return
* @see br.com.arsmachina.dao.hibernate.ReadableDAOImpl#createCriteria(br.com.arsmachina.dao.SortCriterion[])
*/
protected Criteria createCriteria(SortCriterion... sortCriteria) {
return readableDAO.createCriteria(sortCriteria);
}
/**
* Invokes <code>delegate.createCriteria()<code>.
* @param firstIndex
* @param maximumResults
* @param sortCriteria
* @return
* @see br.com.arsmachina.dao.hibernate.ReadableDAOImpl#createCriteria(int, int, br.com.arsmachina.dao.SortCriterion[])
*/
public Criteria createCriteria(int firstIndex, int maximumResults,
SortCriterion... sortCriteria) {
return readableDAO.createCriteria(firstIndex, maximumResults, sortCriteria);
}
/**
* Invokes <code>readableDAO.createExample()<code>.
* @param entity
* @return
* @see br.com.arsmachina.dao.hibernate.ReadableDAOImpl#createExample(java.lang.Object)
*/
protected Example createExample(T entity) {
return readableDAO.createExample(entity);
}
/**
* Returns the entity class handled by this DAO.
*
* @return a {@link Class<T>}.
*/
protected final Class<T> getEntityClass() {
return readableDAO.getEntityClass();
}
/**
* Returns a {@link Session}. This implementation returns
* {@link SessionFactory#getCurrentSession()} and can be overriden if needed.
*
* @return a {@link Session}.
*/
protected Session getSession() {
return getSessionFactory().getCurrentSession();
}
/**
* Returns this DAO's {@link SessionFactory}.
*
* @return a {@link SessionFactory}.
*/
protected final SessionFactory getSessionFactory() {
return readableDAO.getSessionFactory();
}
/**
* Returns the {@link ClassMetadata} for the corresponding entity class.
*
* @return a {@link ClassMetadata}.
*/
final protected ClassMetadata getClassMetadata() {
return readableDAO.getClassMetadata();
}
/**
* Returns the name of the property.
*
* @return a {@link String}.
*/
public String getPrimaryKeyPropertyName() {
return readableDAO.getPrimaryKeyPropertyName();
}
/**
* Concrete {@link ReadableDAOImpl} subclass.
*
* @author Thiago H. de Paula Figueiredo
* @param <T>
* @param <K>
*/
private final class InternalReadableDAOImpl extends ReadableDAOImpl<T, K> {
public InternalReadableDAOImpl(Class<T> clasz, SessionFactory sessionFactory) {
super(clasz, sessionFactory);
}
}
/**
* Concrete {@link WriteableDAOImpl} subclass.
*
* @author Thiago H. de Paula Figueiredo
* @param <T>
* @param <K>
*/
private final class InternalWriteableDAOImpl extends WriteableDAOImpl<T, K> {
public InternalWriteableDAOImpl(Class<T> clasz, SessionFactory sessionFactory) {
super(clasz, sessionFactory);
}
}
}