Hibernate 泛型DAO實現代碼

jopen 9年前發布 | 2K 次閱讀 Java Hibernate


import java.io.Serializable;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.criterion.Criterion;

/**
 * 
 * Hibernate Generic DAO Interface
 *
 * @param <T>  Entity
 * @param <PK> Primary Key
 */
public interface GenericDaoIf<T, PK extends Serializable> {

    /**
     * Get entity by primary key
     * @param id Primary key
     * @return Entity object
     */
    public T get(final PK id);

    /**
     * Load entity by primary key
     * @param id Primary key
     * @return Entity object
     */
    public T load(final PK id);

    /**
     * Remove entity from session, changes to this entity will 
     * not be synchronized with the database
     * @param entity The object to be evicted
     */
    public void evict(T entity);

    /**
     * Save entity
     * @param entity The object to be saved
     * @return The generated identifier
     */
    public PK save(T entity);


    /**
     * Update entity
     * @param entity The object to be updated
     */
    public void update(T entity);

    /**
     * Save or update entity
     * @param entity The object to be save or update
     */
    public void saveOrUpdate(T entity);

    /**
     * Update entity's not-null property
     * (this entity must have a primary key property "id")
     * @param entity The object to be updated
     */
    public void updateSelective(T entity);

    /**
     * Merge entity
     * @param entity The object to be merged into database
     * @return The persistent object
     */
    public T merge(T entity);

    /**
     * Delete entity (actually, delete by primary key)
     * @param entity The object to be deleted
     */
    public void delete(T entity);

    /**
     * Delete entity by primary key, first get then delete
     * @param id Primary key
     */
    public void delete(PK id);

    /**
     * Find all entities
     * @return Query result list
     */
    public List<T> findAll();

    /**
     * Find entities by page
     * @param page Paging object
     * @return Paging query result, Comes with a results list 
     */
    public Page<T> findAll(Page<T> page);

    /**
     * Press the HQL Query object list
     * @param hql 
     *            HQL statement 
     * @param values 
     *            Number of variable parameters 
     * @return Query result list
     */
    public List<T> find(String hql, Object... values);

    /**
     * Press the SQL Query object list
     * @param sql
     *            SQL statement
     * @param values
     *            Number of variable parameters 
     * @return Query result list
     */
    public List<T> findBySql(String sql, Object... values);

    /**
     * Press the HQL query paging .
     * @param page
     *            Paging parameters .
     * @param hql
     *            HQL statement .
     * @param values
     *            Number of variable parameters .
     * @return Paging query results ,Comes with a results list .
     */
    public Page<T> find(Page<T> page, String hql, Object... values);

    /**
     * Press the SQL query paging .
     * @param page
     *            Paging parameters .
     * @param sql
     *            SQL statement .
     * @param values
     *            Number of variable parameters .
     * @return Paging query results ,Comes with a results list .
     */
    public Page<T> findBySql(Page<T> page, String sql, Object... values);

    /**
     * Press the HQL query only object
     * @param hql 
     *            HQL statement
     * @param values 
     *            Number of variable parameters
     * @return A single instance that matches the query, or null if the query returns no results
     */
    public Object findUnique(String hql, Object... values);

    /**
     * Press the SQL query only object
     * @param sql
     *            SQL statement
     * @param values
     *            Number of variable parameters
     * @return A single instance that matches the query, or null if the query returns no results
     */
    public Object findUniqueBySql(String sql, Object... values);

    /**
     * According to the Criterion query object list .
     * @param criterion
     *            Number of variable Criterion .
     * @return Query result list
     */
    public List<T> findByCriteria(Criterion... criterion);

    /**
     * According to the Criterion paging query .
     * @param page
     *            Paging parameters .Including the pageSize, firstResult, orderBy, asc, autoCount .
     *            Where firstResult can be directly specified ,You can also specify pageNo . autoCountSpecifies whether dynamic gets total number of results .
     * @param criterion
     *            Number of variable criterion .
     * @return Paging query results .Comes with a results list and all query parameters .
     */
    public Page<T> findByCriteria(Page<T> page, Criterion... criterion);

    /**
     * Find a list of objects by property .
     * @param propertyName Property name of the entity
     * @param value Property value
     * @return Query result list
     */
    public List<T> findByProperty(String propertyName, Object value);

    /**
     * Find unique object by property .
     * @param propertyName Property name of the entity
     * @param value Property value
     * @return A single instance that matches the query, or null if the query returns no 
     */
    public T findUniqueByProperty(String propertyName, Object value);

    /**
     * Determine the object's property value is unique within the database .
     * @param propertyName Property name of the entity
     * @param newValue New property value
     */
    public boolean isPropertyUnique(String propertyName, Object newValue);

    /**
     * Depending on the query function and argument list to create a Query object ,Subsequent to processing ,The auxiliary function .
     * @param queryString HQL string
     * @param values Number of variable parameters
     * @return Query object
     */
    public Query createQuery(String queryString, Object... values);

    /**
     * Depending on the query function and argument list to create a SQL Query object ,Subsequent to processing ,The auxiliary function .
     * @param queryString SQL string
     * @param values Number of variable parameters
     * @return SQL query object
     */
    public SQLQuery createSQLQuery(String queryString, Object... values);

    /**
     * According to the Criterion conditions create Criteria ,Subsequent to processing ,The auxiliary function .
     * @param criterions Number of variable criterion
     * @return A criteria
     */
    public Criteria createCriteria(Criterion... criterions);

    /**
     * Count HQL query result
     * @param hql HQL statement
     * @param values Number of variable parameters
     * @return Result count
     */
    public long countQueryResult(String hql, Object... values);

    /**
     * Count SQL query result
     * @param sql HQL statement
     * @param values Number of variable parameters
     * @return Result count
     */
    public long countSQLQueryResult(String sql, Object... values);

    /**
     * Through this count query to obtain the total number of objects .
     * @param page Paging object
     * @param c Query criteria
     * @return The total number of objects of the query result.
     */
    public long countCriteriaResult(Page<T> page, Criteria c);

    /**
     * Save entities in batch
     * @param entities The objects to be saved
     * @param batchSize The number of every session flush
     * @return Successful save count
     */
    public int batchSave(List<T> entities, int batchSize);

    /**
     * Update entities in batch
     * @param entities The objects to be updated
     * @param batchSize The number of every session flush
     * @return Successful update count
     */
    public int batchUpdate(List<T> entities, int batchSize);

    /**
     * Save or update entities in batch
     * @param entities The objects to be saved or updated
     * @param batchSize The number of every session flush
     * @return Successful save count or update count
     */
    public int batchSaveOrUpdate(List<T> entities, int batchSize);

    /**
     * Update entities (not-null property) in batch
     * @param entities The objects to be updated
     * @param batchSize The number of every session flush
     * @return Successful update count
     */
    public int batchUpdateSelective(List<T> entities, int batchSize);

    /**
     * Merge entities in batch
     * @param entities The objects to be merged
     * @param batchSize The number of every session flush
     * @return Successful merge count
     */
    public int batchMerge(List<T> entities, int batchSize);

    /**
     * Delete entities in batch
     * @param entities The objects to be deleted
     * @param batchSize The number of every session flush
     * @return successful delete count
     */
    public int batchDelete(List<T> entities, int batchSize);

}


import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projection;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.impl.CriteriaImpl;
import org.hibernate.impl.CriteriaImpl.OrderEntry;
import org.hibernate.transform.ResultTransformer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;

import com.alan.mvnapp.mvn_app.dao.GenericDaoIf;
import com.alan.mvnapp.mvn_app.dao.Page;

/**
 * 
 * Hibernate Generic DAO Implementation
 *
 * @param <T> Entity
 * @param <PK> Primary Key
 */
public class GenericDaoImpl<T, PK extends Serializable> implements GenericDaoIf<T, PK> {

    protected Logger logger = LoggerFactory.getLogger(getClass()); 

    protected SessionFactory sessionFactory;

    protected Class<?> entityClass;

    public GenericDaoImpl() {
        this.entityClass = (Class<?>) ((ParameterizedType) getClass()
                .getGenericSuperclass()).getActualTypeArguments()[0];
    }

    public GenericDaoImpl(SessionFactory sessionFactory, Class<T> entityClass) {
        this.sessionFactory = sessionFactory;
        this.entityClass = entityClass;
    }

    @SuppressWarnings("unchecked")
    public T get(final PK id) {
        return (T) sessionFactory.getCurrentSession().get(entityClass, id);
    }

    @SuppressWarnings("unchecked")
    public T load(final PK id) {
        return (T) sessionFactory.getCurrentSession().load(entityClass, id);
    }

    public void evict(T entity) {
        sessionFactory.getCurrentSession().evict(entity);
    }

    @SuppressWarnings("unchecked")
    public PK save(T entity) {
        Assert.notNull(entity);
        PK pk = (PK) sessionFactory.getCurrentSession().save(entity);
        logger.info("save entity: {}", entity);
        return pk;
    }

    public void update(T entity) {
        Assert.notNull(entity);
        sessionFactory.getCurrentSession().update(entity);
        logger.info("update entity: {}", entity);
    }

    public void saveOrUpdate(T entity) {
        Assert.notNull(entity);
        sessionFactory.getCurrentSession().saveOrUpdate(entity);
        logger.info("save or update entity: {}", entity);
    }

    public void updateSelective(T entity) {
        Assert.notNull(entity);
        Field[] fields = entity.getClass().getDeclaredFields();
        List<String> params = new ArrayList<String>();
        List<Object> values = new ArrayList<Object>();
        for(Field field : fields) {
            String fieldName = field.getName();
            field.setAccessible(true);
            Object value = ReflectionUtils.getField(field, entity);
            if(value != null) {
                params.add(fieldName);
                values.add(value);
            }
        }
        if(!params.isEmpty()) {
            StringBuffer sb = new StringBuffer("update " 
                    + entityClass.getSimpleName() + " set ");
            for(int i = 0; i < params.size(); i++) {
                sb.append(params.get(i) + " = ? ");
                if(i < params.size() - 1) {
                    sb.append(", ");
                }
            }
            Field pkField = ReflectionUtils.findField(entityClass, "id");
            Assert.notNull(pkField);
            pkField.setAccessible(true);
            sb.append(" where id = ? ");
            values.add(ReflectionUtils.getField(pkField, entity));
            createQuery(sb.toString(), values.toArray()).executeUpdate();
            logger.info("update entity selecitive: {}" + entity);
        }
    }

    @SuppressWarnings("unchecked")
    public T merge(T entity) {
        Assert.notNull(entity);
        T t = (T) sessionFactory.getCurrentSession().merge(entity);
        logger.info("merge entity: {}", entity);
        return t;
    }

    public void delete(T entity) {
        Assert.notNull(entity);
        sessionFactory.getCurrentSession().delete(entity);
        logger.info("delete entity: {}", entity);
    }

    public void delete(PK id) {
        Assert.notNull(id);
        delete(get(id));
    }

    public List<T> findAll() {
        return findByCriteria();
    }

    public Page<T> findAll(Page<T> page) {
        return findByCriteria(page);
    }

    @SuppressWarnings("unchecked")
    public List<T> find(String hql, Object... values) {
        return (List<T>)createQuery(hql, values).list();
    }

    @SuppressWarnings("unchecked")
    public List<T> findBySql(String sql, Object... values) {
        return (List<T>)createSQLQuery(sql, values).addEntity(entityClass).list();
    }

    @SuppressWarnings("unchecked")
    public Page<T> find(Page<T> page, String hql, Object... values) {
        Assert.notNull(page);
        if(page.isAutoCount()) {
            page.setTotalCount(countQueryResult(hql, values));
        }
        Query q = createQuery(hql, values);
        if(page.isFirstSetted()) {
            q.setFirstResult(page.getFirst());
        }
        if(page.isPageSizeSetted()) {
            q.setMaxResults(page.getPageSize());
        }
        page.setResult((List<T>)q.list());
        return page;
    }

    @SuppressWarnings("unchecked")
    public Page<T> findBySql(Page<T> page, String sql, Object... values) {
        Assert.notNull(page);
        if(page.isAutoCount()) {
            page.setTotalCount(countSQLQueryResult(sql, values));
        }
        SQLQuery q = createSQLQuery(sql, values);
        if(page.isFirstSetted()) {
            q.setFirstResult(page.getFirst());
        }
        if(page.isPageSizeSetted()) {
            q.setMaxResults(page.getPageSize());
        }
        page.setResult((List<T>)q.addEntity(entityClass).list());
        return page;
    }

    public Object findUnique(String hql, Object... values) {
        return createQuery(hql, values).uniqueResult();
    }

    public Object findUniqueBySql(String sql, Object... values) {
        return createSQLQuery(sql, values).addEntity(entityClass).uniqueResult();
    }

    @SuppressWarnings("unchecked")
    public List<T> findByCriteria(Criterion... criterion) {
        return (List<T>)createCriteria(criterion).list();
    }

    @SuppressWarnings("unchecked")
    public Page<T> findByCriteria(Page<T> page, Criterion... criterion) {
        Assert.notNull(page);
        Criteria c = createCriteria(criterion);
        if(page.isAutoCount()) {
            page.setTotalCount(countCriteriaResult(page, c));
        }
        if(page.isFirstSetted()) {
            c.setFirstResult(page.getFirst());
        }
        if(page.isPageSizeSetted()) {
            c.setMaxResults(page.getPageSize());
        }
        if(page.isOrderBySetted()) {
            if(page.getOrder().toUpperCase().equals("AES")) {
                c.addOrder(Order.asc(page.getOrderBy()));
            } else {
                c.addOrder(Order.desc(page.getOrderBy()));
            }
        }
        page.setResult((List<T>)c.list());
        return page;
    }

    @SuppressWarnings("unchecked")
    public List<T> findByProperty(String propertyName, Object value) {
        Assert.hasText(propertyName);
        return (List<T>) createCriteria(Restrictions.eq(propertyName, value)).list();
    }

    @SuppressWarnings("unchecked")
    public T findUniqueByProperty(String propertyName, Object value) {
        Assert.hasText(propertyName);
        return (T)createCriteria(Restrictions.eq(propertyName, value)).uniqueResult();
    }

    public boolean isPropertyUnique(String propertyName, Object newValue) {
        if(newValue == null) return false;
        try {
            Object obj = findUniqueByProperty(propertyName, newValue);
            return obj == null;
        } catch (HibernateException e) {
            return false;
        }
    }

    public Query createQuery(String queryString, Object... values) {
        Assert.hasText(queryString);
        Query queryObject = sessionFactory.getCurrentSession().createQuery(queryString);
        if(values != null) {
            for(int i = 0; i < values.length; i++) {
                queryObject.setParameter(i, values[i]);
            }
        }
        return queryObject;
    }

    public SQLQuery createSQLQuery(String queryString, Object... values) {
        Assert.hasText(queryString);
        SQLQuery queryObject = sessionFactory.getCurrentSession().createSQLQuery(queryString);
        if(values != null) {
            for(int i = 0; i < values.length; i++) {
                queryObject.setParameter(i, values[i]);
            }
        }
        return queryObject;
    }

    public Criteria createCriteria(Criterion... criterions) {
        Criteria criteria = sessionFactory.getCurrentSession().createCriteria(entityClass);
        for(Criterion c : criterions) {
            criteria.add(c);
        }
        return criteria;
    }

    public long countQueryResult(String hql, Object... values) {
        hql = hql.replaceAll(" [Ff][Rr][Oo][Mm] ", " from ");
        String str = hql.toLowerCase();
        if(!StringUtils.contains(str, "group by")
                && !StringUtils.contains(str, "union")
                && !StringUtils.contains(str, "minus")
                && !StringUtils.contains(str, "intersect")
                && !StringUtils.contains(StringUtils.substringAfter(str, "from"), "(")
                ) {
            str = "select count(*) from " + StringUtils.substringAfter(hql, "from");
            return ((Number)createQuery(hql, values).iterate().next()).longValue();
        } else {
            throw new HibernateException("not support this HQL : " + hql);
        }
    }

    public long countSQLQueryResult(String sql, Object... values) {
        String str = sql.toLowerCase();
        String beforeFrom = StringUtils.substringBefore(str, "from");
        if(StringUtils.countMatches(beforeFrom, "(") 
                != StringUtils.countMatches(beforeFrom, ")")
                || StringUtils.contains(str, "group by")
                || StringUtils.contains(str, "union")
                || StringUtils.contains(str, "minus")
                || StringUtils.contains(str, "intersect")) {
            str = "select count(*) from (" + sql + ") as tmp";
        } else {
            str = "select count(*) from " + 
                    StringUtils.substringAfter(str, "from");
        }
        Object ret = createSQLQuery(str, values).uniqueResult();
        return (ret == null ? 0 : ((Number)ret).longValue());
    }

    @SuppressWarnings("unchecked")
    public long countCriteriaResult(Page<T> page, Criteria c) {
        CriteriaImpl cimpl = (CriteriaImpl)c;

        // First Projection, ResultTransformer, OrderBy out ,Empty after a three Count operations 
        Projection projection = cimpl.getProjection();
        ResultTransformer transformer = cimpl.getResultTransformer();

        List<CriteriaImpl.OrderEntry> orderEntries = null;
        try {
            Field orderEntriesField = cimpl.getClass().getDeclaredField("orderEntries");
            orderEntriesField.setAccessible(true);
            orderEntries = (List<OrderEntry>) ReflectionUtils.getField(
                    orderEntriesField, cimpl);
            ReflectionUtils.setField(
                    orderEntriesField, cimpl, 
                    new ArrayList<OrderEntry>());
        } catch (Exception e) {
            logger.error("Not may throw an exception :{}", e.getMessage());
        }

        // Do Count query 
        long totalCount = (Long) c.setProjection(Projections.rowCount())
                .uniqueResult();
        if (totalCount < 1)
            return -1;

        // Will the Projection and OrderBy before conditions back to go back 
        c.setProjection(projection);

        if (projection == null) {
            c.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);
        }
        if (transformer != null) {
            c.setResultTransformer(transformer);
        }

        try {
            Field orderEntriesField = cimpl.getClass().getDeclaredField("orderEntries");
            orderEntriesField.setAccessible(true);
            ReflectionUtils.setField(orderEntriesField, cimpl, orderEntries);
        } catch (Exception e) {
            logger.error("Not may throw an exception :{}", e.getMessage());
        }

        return totalCount;

    }

    private int tuneBatchSize(int batchSize) {
        if(batchSize < 20) {
            batchSize = 20;
        } else if(batchSize > 200) {
            batchSize = 200;
        }
        return batchSize;
    }

    public int batchSave(List<T> entities, int batchSize) {
        Assert.notEmpty(entities);
        batchSize = tuneBatchSize(batchSize);
        int count = 0;
        Session session = sessionFactory.getCurrentSession();
        for(int i = 0; i < entities.size(); i++) {
            session.save(entities.get(i));
            if(i % batchSize == 0 || i == entities.size() - 1) {
                session.flush();
                session.clear();
            }
            count++;
        }
        return count;
    }

    public int batchUpdate(List<T> entities, int batchSize) {
        Assert.notEmpty(entities);
        batchSize = tuneBatchSize(batchSize);
        int count = 0;
        Session session = sessionFactory.getCurrentSession();
        for(int i = 0; i < entities.size(); i++) {
            session.update(entities.get(i));
            if(i % batchSize == 0 || i == entities.size() - 1) {
                session.flush();
                session.clear();
            }
            count++;
        }
        return count;
    }

    public int batchSaveOrUpdate(List<T> entities, int batchSize) {
        Assert.notEmpty(entities);
        batchSize = tuneBatchSize(batchSize);
        int count = 0;
        Session session = sessionFactory.getCurrentSession();
        for(int i = 0; i < entities.size(); i++) {
            session.saveOrUpdate(entities.get(i));
            if(i % batchSize == 0 || i == entities.size() - 1) {
                session.flush();
                session.clear();
            }
            count++;
        }
        return count;
    }

    public int batchUpdateSelective(List<T> entities, int batchSize) {
        Assert.notEmpty(entities);
        batchSize = tuneBatchSize(batchSize);
        int count = 0;
        Session session = sessionFactory.getCurrentSession();
        for(int i = 0; i < entities.size(); i++) {
            updateSelective(entities.get(i));
            if(i % batchSize == 0 || i == entities.size() - 1) {
                session.flush();
                session.clear();
            }
            count++;
        }
        return count;
    }

    public int batchMerge(List<T> entities, int batchSize) {
        Assert.notEmpty(entities);
        batchSize = tuneBatchSize(batchSize);
        int count = 0;
        Session session = sessionFactory.getCurrentSession();
        for(int i = 0; i < entities.size(); i++) {
            session.merge(entities.get(i));
            if(i % batchSize == 0 || i == entities.size() - 1) {
                session.flush();
                session.clear();
            }
            count++;
        }
        return count;
    }

    public int batchDelete(List<T> entities, int batchSize) {
        Assert.notEmpty(entities);
        batchSize = tuneBatchSize(batchSize);
        int count = 0;
        Session session = sessionFactory.getCurrentSession();
        for(int i = 0; i < entities.size(); i++) {
            session.delete(entities.get(i));
            if(i % batchSize == 0 || i == entities.size() - 1) {
                session.flush();
                session.clear();
            }
            count++;
        }
        return count;
    }

}


 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!