通用DAO和包装器

时间:2010-11-23 00:07:29

标签: hibernate dao

为了完成一个uni项目,我需要创建一个通用的DAO。

我遵循了Manning的书中使用hibernate编写的Java持久性中的泛型DAO设计。最终得到了以下方法。

findById(ID id, boolean lock)
findAll()
findByExample(T example)
makePersistent(T entity)
makeTransient(T entity)
flush()
clear()

问题是这些方法对我的项目来说还不够,它包括搜索实体,排序和分页。我知道我可以通过创建像

这样的方法来做到这一点
List<T> find(DetachedCriteria dc)

问题是这意味着我将hibernate接口暴露给业务层,我不希望这样。

我想创建一个界面说MyCriteria和一个类说MyCriteriaImpl,它会和DetachedCriteria一样,但是让我通过改变实现来改变持久性提供者。我想这是可能的。

问题在于我没有时间编写这样的代码。

我想知道的是,是否有一个模式可以让我创建MyCriteria接口,而在MyCriteriaImpl中只调用hibernate criteria api的方法。

喜欢:

MyCriteriaImpl mci = new MyCriteriaImpl();
mci.addRestrictionLike(property, String value);

这只是打电话给:

DetachedCriteria dc = new DetachedCriteria();
dc.add(Restrictions.like(property, value) 

由于

2 个答案:

答案 0 :(得分:1)

使用这个。它具有分页和lucene集成。我为我的一个项目创建了这个。确保每个DAO都从它延伸。拿出你不需要的东西。

package com.isavera.hibernate;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.commons.lang.StringUtils;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.queryParser.MultiFieldQueryParser;
import org.apache.lucene.queryParser.ParseException;
import org.hibernate.Criteria;
import org.hibernate.LockMode;
import org.hibernate.Query;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.criterion.Criterion;
import org.hibernate.search.FullTextSession;
import org.hibernate.search.Search;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.dao.ConcurrencyFailureException;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import com.isavera.actions.utils.Application;

@SuppressWarnings("serial")
@Transactional
public abstract class AbstractDAOImpl<E> extends HibernateDaoSupport implements AbstractDAO<E>, ApplicationContextAware {


private static final String CLASS_NAME = AbstractDAOImpl.class.getName();

private static final Logger LOG = Logger.getLogger(CLASS_NAME);

private static ApplicationContext _applicationContext;

private final Class<? extends E> _entityClass;

/**
 * @param entityClass
 */
public AbstractDAOImpl(Class<? extends E> entityClass) {
    super();

    _entityClass = entityClass;
}


public void delete(E entity) {
    LOG.entering(CLASS_NAME, "delete", entity);

    getHibernateTemplate().delete(entity);

    LOG.exiting(CLASS_NAME, "delete");
}

public void evict(E entity) {
    LOG.entering(CLASS_NAME, "evict", entity);

    getHibernateTemplate().evict(entity);

    LOG.exiting(CLASS_NAME, "evict");
}

public void deleteAll(Collection<E> entities) {
    getHibernateTemplate().deleteAll(entities);
}

@SuppressWarnings("unchecked")
public List<E> findByNamedQuery(String queryName) {
    return getHibernateTemplate().findByNamedQuery(queryName);
}

@SuppressWarnings("unchecked")
public List<E> findByNamedQueryAndNamedParam(String queryName, String paramName, Object value) {
    return getHibernateTemplate().findByNamedQueryAndNamedParam(queryName, paramName, value);
}

@SuppressWarnings("unchecked")
public List<E> findByNamedQueryAndNamedParam(String queryName, String[] paramNames, Object[] values) {
    return getHibernateTemplate().findByNamedQueryAndNamedParam(queryName, paramNames, values);
}

public E get(Serializable id) {
    LOG.entering(CLASS_NAME, "get", id);

    @SuppressWarnings("unchecked")
    E entity = (E) getHibernateTemplate().get(_entityClass, id);

    LOG.exiting(CLASS_NAME, "get", entity);

    return entity;
}

public List<E> get(Criterion... criterion) {
    LOG.entering(CLASS_NAME, "get", criterion);

    Criteria criteria = getSession().createCriteria(_entityClass);

    for (Criterion c : criterion) {
        criteria.add(c);
    }

    @SuppressWarnings("unchecked")
    List<E> list = new ArrayList<E>(criteria.list());

    LOG.exiting(CLASS_NAME, "get", list);

    return list;
}

public boolean isEntityAttached(E entity) {
    return getHibernateTemplate().getSessionFactory().getCurrentSession().contains(entity);
}

public E load(Serializable id) {
    LOG.entering(CLASS_NAME, "load", id);

    @SuppressWarnings("unchecked")
    E entity = (E) getHibernateTemplate().load(_entityClass, id);

    LOG.exiting(CLASS_NAME, "load", entity);

    return entity;
}

public E load(Serializable id, LockMode lockMode) {
    LOG.entering(CLASS_NAME, "load", new Object[] { id, lockMode });

    @SuppressWarnings("unchecked")
    E entity = (E) getHibernateTemplate().load(_entityClass, id, lockMode);

    LOG.exiting(CLASS_NAME, "load", entity);

    return entity;
}

public void load(E entity, Serializable id) {
    LOG.entering(CLASS_NAME, "load", new Object[] { entity, id });

    getHibernateTemplate().load(entity, id);

    LOG.exiting(CLASS_NAME, "load");
}

public void lock(E entity, LockMode lockMode) {
    LOG.entering(CLASS_NAME, "lock", new Object[] { entity, lockMode });

    getHibernateTemplate().lock(entity, lockMode);

    LOG.exiting(CLASS_NAME, "lock");
}



public void saveOrUpdateAll(Collection<E> entities) {
    getHibernateTemplate().saveOrUpdateAll(entities);
}

@SuppressWarnings("unchecked")
public E merge(E entity) {
    LOG.entering(CLASS_NAME, "merge", entity);

    E persistentEntity = (E) getHibernateTemplate().merge(entity);

    LOG.exiting(CLASS_NAME, "merge", persistentEntity);

    return persistentEntity;
}

public void refresh(E entity) {
    LOG.entering(CLASS_NAME, "refresh", entity);

    getHibernateTemplate().refresh(entity);

    LOG.exiting(CLASS_NAME, "refresh");
}

public Long save(E entity) {
    LOG.entering(CLASS_NAME, "save", entity);

    LOG.exiting(CLASS_NAME, "save");

    return (Long) getHibernateTemplate().save(entity);
}

public void saveOrUpdate(E entity) {
    LOG.entering(CLASS_NAME, "saveOrUpdate", entity);

    getHibernateTemplate().saveOrUpdate(entity);

    LOG.exiting(CLASS_NAME, "saveOrUpdate");
}

public void update(E entity) {
    LOG.entering(CLASS_NAME, "update", entity);

    getHibernateTemplate().update(entity);

    LOG.exiting(CLASS_NAME, "update");
}

/**
 * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
 */
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    setStaticApplicationContext(applicationContext);
}

private static void setStaticApplicationContext(ApplicationContext applicationContext) {
    _applicationContext = applicationContext;
}

/**
 * @param queryName
 * @return count
 */
protected int getCounter(String queryName) {
    @SuppressWarnings("unchecked")
    List<Number> counterList = getHibernateTemplate().findByNamedQuery(queryName);

    return counterList == null || counterList.isEmpty() ? 0 : counterList.iterator().next().intValue();
}

/**
 * @param queryName
 * @param paramName
 * @param value
 * @return count
 */
protected int getCounter(String queryName, String paramName, Object value) {
    @SuppressWarnings("unchecked")
    List<Number> counterList = getHibernateTemplate().findByNamedQueryAndNamedParam(queryName, paramName, value);

    return counterList == null || counterList.isEmpty() ? 0 : counterList.iterator().next().intValue();
}

/**
 * @param queryName
 * @param paramNames
 * @param values
 * @return count
 */
protected int getCounter(String queryName, String[] paramNames, Object[] values) {
    @SuppressWarnings("unchecked")
    List<Number> counterList = getHibernateTemplate().findByNamedQueryAndNamedParam(queryName, paramNames, values);

    return counterList == null || counterList.isEmpty() ? 0 : counterList.iterator().next().intValue();
}

public List<E> narrowSearch(String keyword) {
    List<E> result = Collections.EMPTY_LIST;
    if (StringUtils.isBlank(keyword)) {
        return result;
    }
    try {
        Method method = _entityClass.getMethod("SEARCHABLE_FIELDS");
        if (method == null) {
            throw new RuntimeException(_entityClass + " should respond to static method call - SEARCHABLE_FIELDS");
        }
        result = narrowSearch(keyword, (String[]) method.invoke(null, null), _entityClass);
    } catch (Exception ex) {
        ex.printStackTrace();
    }
    return result;
}

public List<E> search(String keyword) {
    List<E> result = Collections.EMPTY_LIST;
    if (StringUtils.isBlank(keyword)) {
        return result;
    }
    try {
        Method method = _entityClass.getMethod("SEARCHABLE_FIELDS");
        if (method == null) {
            throw new RuntimeException(_entityClass + " should respond to static method call - SEARCHABLE_FIELDS");
        }
        result = search(keyword, (String[]) method.invoke(null, null), _entityClass);
    } catch (Exception ex) {
        ex.printStackTrace();
    }
    return result;
}

private List<E> search(String keyword, String[] fields, Class clazz) {
    Map<String, Integer> paginationOptions = Application.getPaginationOptions();
    Integer pageNumber = Integer.valueOf(1);
    Integer perPage = Integer.valueOf(5);

    if (paginationOptions.containsKey("perPage")) {
        pageNumber = paginationOptions.get("pageNumber");
        perPage = paginationOptions.get("perPage");
    }

    FullTextSession fullTextSession = Search.getFullTextSession(getHibernateTemplate().getSessionFactory().getCurrentSession());

    // create native Lucene query
    MultiFieldQueryParser parser = new MultiFieldQueryParser(fields, new StandardAnalyzer());
    org.apache.lucene.search.Query query;
    try {
        query = parser.parse(keyword);
        // wrap Lucene query in a org.hibernate.Query
        org.hibernate.search.FullTextQuery hibQuery = fullTextSession.createFullTextQuery(query, clazz);
        hibQuery.setFirstResult((pageNumber - 1) * perPage);
        hibQuery.setMaxResults(perPage);
        Application.setResultSize(hibQuery.getResultSize());
        // execute search
        return hibQuery.list();
    } catch (ParseException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    return null;
}

private List<E> narrowSearch(String keyword, String[] fields, Class clazz) {
    /**
     * Need to identify better way of doing this for performance reasons.
     */
    List<E> results = new ArrayList<E>();
    for (String word : keyword.split(" ")) {
        if (results.isEmpty()) {
            results.addAll(search(word, fields, clazz));
        } else {
            results.retainAll(search(word, fields, clazz));
        }
    }
    return results;
}

protected static <T extends AbstractDAO<?>> T getDAO(String beanName, Class<T> clazz) {
    return clazz.cast(_applicationContext.getBean(beanName, clazz));
}


protected int getCount(List<Number> counterList) {
    return counterList == null || counterList.isEmpty() ? 0 : counterList.iterator().next().intValue();
}

@SuppressWarnings("unchecked")
protected List paginateByNamedQueryAndNamedParam(String hqlName, Map<String, Object> params) {
    Query namedQuery = getHibernateTemplate().getSessionFactory().getCurrentSession().getNamedQuery(hqlName);
    configurePagination(namedQuery);

    for (Entry<String, Object> parameter : params.entrySet()) {
        if (parameter.getValue() instanceof Collection) {
            namedQuery.setParameterList(parameter.getKey(), (Collection) parameter.getValue());
        } else if (parameter.getValue() instanceof Object[]) {
            namedQuery.setParameterList(parameter.getKey(), (Object[]) parameter.getValue());
        } else {
            namedQuery.setParameter(parameter.getKey(), parameter.getValue());
        }

    }
    return namedQuery.list();
}

@SuppressWarnings("unchecked")
protected List paginateByNamedQuery(String hqlName) {
    Query namedQuery = getHibernateTemplate().getSessionFactory().getCurrentSession().getNamedQuery(hqlName);
    configurePagination(namedQuery);

    List result = namedQuery.list();

    resetPagination(namedQuery);

    return result;
}

private void resetPagination(Query namedQuery) {
    getHibernateTemplate().setMaxResults(0);
}

private void configurePagination(Query namedQuery) {
    Integer pageNumber = Application.getPaginationOptions().get("pageNumber");
    Integer perPage = Application.getPaginationOptions().get("perPage");

    if (pageNumber != null && pageNumber > 1) {
        namedQuery.setFirstResult((pageNumber - 1) * perPage);
    }
    namedQuery.setMaxResults(perPage == null ? 5 : perPage);
}



}

答案 1 :(得分:0)

Hades提供了通用DAO接口所需的全部功能。如果您可以使用它替换您自己种植的东西,或者如果您只是寻找参考,您可以浏览它的代码。它支持分页等。