【问题标题】:Generic DAO and Wrapper通用 DAO 和包装器
【发布时间】:2010-11-23 00:07:29
【问题描述】:

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

我遵循 Manning 的 Java persistence with hibernate 一书中的通用 DAO 设计。最终得到以下方法。

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

问题是这些方法对于我的项目来说是不够的,我的项目包括搜索实体、对它们进行排序和分页。我知道我可以通过创建类似的方法来做到这一点

List<T> find(DetachedCriteria dc)

问题在于,这意味着我向业务层公开了一个休眠接口,而我不希望这样做。

我想创建一个说 MyCriteria 的接口和一个说 MyCriteriaImpl 的类,它们的作用与 DetachedCriteria 相同,但允许我通过仅更改实现来更改持久性提供程序。我想这是可能的。

问题是我没有时间写这样的代码。

我想知道是否有一种模式可以让我创建 MyCriteria 接口,并且在 MyCriteriaImpl 中只需调用休眠条件 api 的方法。

喜欢:

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

这只是意味着调用:

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

谢谢

【问题讨论】:

    标签: hibernate dao


    【解决方案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);
    }
    
    
    
    }
    

    【讨论】:

    • 嗨,在这个类中,您将公开这个方法 public List get(Criterion...criterion) 向客户端公开休眠 API,这是我一直试图解决的问题.此外,我更喜欢使用 Criteria API 而不是 HQL(从来没有真正喜欢过它)。
    • 我相信 Criteria API 比 HQL 慢。所以尝试使用它。
    【解决方案2】:

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

    【讨论】:

    • 嗨,这并不是关于使用通用 dao(我已经找到了 hibernate-generic-dao,它具有我想要的所有功能)。当您需要针对已定义问题的解决方案时,更多的是使用正确的模式。这就是为什么我想要一个让我使用 DetachedCriteria 类但通过实例化一个不是来自休眠 api 的对象的模式。
    猜你喜欢
    • 2010-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-27
    • 1970-01-01
    • 2022-06-13
    • 2015-08-08
    • 2020-05-12
    相关资源
    最近更新 更多