为了完成一个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)
由于
答案 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接口所需的全部功能。如果您可以使用它替换您自己种植的东西,或者如果您只是寻找参考,您可以浏览它的代码。它支持分页等。