免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
hibernate DAO 泛型 另

  一個(gè)好用的hibernate泛型dao 收藏
以前從springside2.0上搞下來的很好用的,基本實(shí)現(xiàn)dao零編碼只要配置xml文件就行了。

先看圖:


 
一共4層,com.demonstration.hibernate.basedao是我加的用來進(jìn)一步解耦hibernate和spring的耦合。
原來的官方解釋如下:
SpringSide對Hibernate做了三層封裝:

第一層:HibernateGenericDao,基于spring的HibernateDaoSupport,但加入了分頁函數(shù)與各種Finder函數(shù),并使用泛型避免了返回值強(qiáng)制類型轉(zhuǎn)換。

第二層:HibernateEntityDao,基于HibernateGenericDao,用泛型聲明Dao所管理的Entity類,默認(rèn)擁有該entity的CRUD方法。

第三層:HibernateExtendDao,基于HibernateEntityDao,主要擴(kuò)展各種選擇性的功能。

關(guān)于三個(gè)類的詳細(xì)注解請看JavaDoc,大致描述如下:

1 HibernateGenericDao
   在Spring HibernateDaoSupport基礎(chǔ)上封裝的DAO,功能如下:

   1.應(yīng)用泛型:使得find(), get() 這些函數(shù)不再返回Object,而是返回T,不再需要強(qiáng)制類型轉(zhuǎn)換。

   2.提供各種finder的簡便函數(shù)
      應(yīng)用了JDK5可變參數(shù)的hsql查詢函數(shù):List find(String hql, Object... values),支持find(hql),find(hql, param1); find(hql,param1,param2);find(hql,new Object[] {param1,param2}) 四種接口。

      簡單查詢的簡化函數(shù):findBy(Class entityClass,String name,Object value) ,findUniqueBy(Class entityClass,String name, Object value),findByLike(Class entityClass,String name,Object value)

   3.獲得設(shè)置好的Query和Criteria:createQuery(String hql,Object... values)  和 createCriteria(Class<T> entityClass,Criterion... criterions)

      Spring并沒有很好的接口封裝支持firstResult, maxResult, fetchsize,cache,cacheRegion 等多個(gè)查詢參數(shù),所以springside寧愿返回已設(shè)置好查詢條件的Query和Criteria,讓大家繼續(xù)剩下的參數(shù)設(shè)置,最后再執(zhí)行 list(),注意那幾個(gè)參數(shù)可以連續(xù)設(shè)置的,如:

createQuery(hql,param1).setFirstResult(10).setMaxResult(20).list();   4.分頁函數(shù):Page pagedQuery(Criteria criteria, int pageNo, int pageSize) 和Page pagedQuery(String hql, int pageNo, int pageSize, Object... args)

      Page是SpringSide自行封裝的一個(gè)典型Page類,pagedQuery與hibernate自身分頁查詢的差別是先運(yùn)行一次count,獲得符合條件的總記錄數(shù)。

      如果查詢不需要總記錄數(shù),用普通的hibernate API,加上setFirstResult(),setMaxResult()就解決,不需要pagedQuery()。

   5.判別對象屬性在數(shù)據(jù)庫中唯一的函數(shù):isUnique(Class<T> entityClass,Object entity,String names)。

2. HibernateEntityDao
    所有UserManager, ProductManager之類只管理一類對象的Manager類的基類,只需要在類定義處聲明Entity類型即可

public class BookManager extends HibernateEntityDao<Book> {
}  通過<Book>的定義,避免了HibernateGenericDao類各方法中必有的Class entityClass參數(shù)。

  如果需要操作其他的Entity,比如BookManager可能需要處理Category(圖書目錄),可以注入CategoryManager。無需擔(dān)心事務(wù)的問題,JavaEE的默認(rèn)事務(wù)模型已能很好處理。

  如果沒有對應(yīng)的CategoryManager,或者各種原因不想注入的話,可以使用BookManager繼承自 HibernateGenericDao的帶entityClass參數(shù)的函數(shù)來操作Category的增刪改,如Category category= this.get(Category.class, 1);

3. HibernateExtendDao
      此類演示SpringSide 所作的一些擴(kuò)展,大家可以按照自己的需要進(jìn)行修改和擴(kuò)展。

     1. 支持對象不能被直接刪除,只能設(shè)置狀態(tài)列為無效。
        接口UndeleteableEntityOperation,定義了要支持此功能必須實(shí)現(xiàn)的函數(shù)。

        可以有接口(UndeletableEntity)和annotation(@Undeletable)兩種形式來定義無效列,annotation列形式還可以定義標(biāo)識對象已刪除的狀態(tài)屬性的名稱,用接口則必須實(shí)現(xiàn)setStatus()接口,在里面操作實(shí)際的狀態(tài)屬性。

第四層就是把HibernateEntityDao和HibernateExtendDao以屬性注入的方式注入到basedao,IBasedao就全局接口程序中使用的就是它,這個(gè)接口的實(shí)現(xiàn)全調(diào)用HibernateEntityDao和HibernateExtendDao的方法。方便以后的更改和替換,這樣IBasedao接口不變就不要修改業(yè)務(wù)層的代碼了。


代碼如下(從下到上):

Page.java

package com.demonstration.hibernate.dao.support;

import java.io.Serializable;
import java.util.ArrayList;
/**
 * 分頁對象. 包含當(dāng)前頁數(shù)據(jù)及分頁信息如總記錄數(shù).
 *
 * @author springside
 * 
 */
@SuppressWarnings("serial")
public class Page implements Serializable {

    private static int DEFAULT_PAGE_SIZE = 20;

    private int pageSize = DEFAULT_PAGE_SIZE; // 每頁的記錄數(shù)

    private long start; // 當(dāng)前頁第一條數(shù)據(jù)在List中的位置,從0開始

    private Object data; // 當(dāng)前頁中存放的記錄,類型一般為List

    private long totalCount; // 總記錄數(shù)

    /**
     * 構(gòu)造方法,只構(gòu)造空頁.
     */
    @SuppressWarnings("unchecked")
    public Page() {
        this(0, 0, DEFAULT_PAGE_SIZE, new ArrayList());
    }

    /**
     * 默認(rèn)構(gòu)造方法.
     *
     * @param start  本頁數(shù)據(jù)在數(shù)據(jù)庫中的起始位置
     * @param totalSize 數(shù)據(jù)庫中總記錄條數(shù)
     * @param pageSize  本頁容量
     * @param data    本頁包含的數(shù)據(jù)
     */
    public Page(long start, long totalSize, int pageSize, Object data) {
        this.pageSize = pageSize;
        this.start = start;
        this.totalCount = totalSize;
        this.data = data;
    }

    /**
     * 取總記錄數(shù).
     */
    public long getTotalCount() {
        return this.totalCount;
    }

    /**
     * 取總頁數(shù).
     */
    public long getTotalPageCount() {
        if (totalCount % pageSize == 0)
            return totalCount / pageSize;
        else
            return totalCount / pageSize + 1;
    }

    /**
     * 取每頁數(shù)據(jù)容量.
     */
    public int getPageSize() {
        return pageSize;
    }

    /**
     * 取當(dāng)前頁中的記錄.
     */
    public Object getResult() {
        return data;
    }

    /**
     * 取該頁當(dāng)前頁碼,頁碼從1開始.
     */
    public long getCurrentPageNo() {
        return start / pageSize + 1;
    }

    /**
     * 該頁是否有下一頁.
     */
    public boolean hasNextPage() {
        return this.getCurrentPageNo() < this.getTotalPageCount() - 1;
    }

    /**
     * 該頁是否有上一頁.
     */
    public boolean hasPreviousPage() {
        return this.getCurrentPageNo() > 1;
    }

    /**
     * 獲取任一頁第一條數(shù)據(jù)在數(shù)據(jù)集的位置,每頁條數(shù)使用默認(rèn)值.
     *
     * @see #getStartOfPage(int,int)
     */
    protected static int getStartOfPage(int pageNo) {
        return getStartOfPage(pageNo, DEFAULT_PAGE_SIZE);
    }

    /**
     * 獲取任一頁第一條數(shù)據(jù)在數(shù)據(jù)集的位置.
     *
     * @param pageNo   從1開始的頁號
     * @param pageSize 每頁記錄條數(shù)
     * @return 該頁第一條數(shù)據(jù)
     */
    public static int getStartOfPage(int pageNo, int pageSize) {
        return (pageNo - 1) * pageSize;
    }
}
GenericsUtils.java

package com.demonstration.hibernate.dao.support;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Generics的util類.
 *
 * @author springside
 * 
 */
public class GenericsUtils {
    private static final Log log = LogFactory.getLog(GenericsUtils.class);

    private GenericsUtils() {
    }

    /**
     * 通過反射,獲得定義Class時(shí)聲明的父類的范型參數(shù)的類型. 如public BookManager extends GenricManager<Book>
     *
     * @param clazz The class to introspect
     * @return the first generic declaration, or <code>Object.class</code> if cannot be determined
     */
    @SuppressWarnings("unchecked")
    public static Class getSuperClassGenricType(Class clazz) {
        return getSuperClassGenricType(clazz, 0);
    }

    /**
     * 通過反射,獲得定義Class時(shí)聲明的父類的范型參數(shù)的類型. 如public BookManager extends GenricManager<Book>
     *
     * @param clazz clazz The class to introspect
     * @param index the Index of the generic ddeclaration,start from 0.
     * @return the index generic declaration, or <code>Object.class</code> if cannot be determined
     */
    @SuppressWarnings("unchecked")
    public static Class getSuperClassGenricType(Class clazz, int index) {

        Type genType = clazz.getGenericSuperclass();

        if (!(genType instanceof ParameterizedType)) {
            log.warn(clazz.getSimpleName() + "'s superclass not ParameterizedType");
            return Object.class;
        }

        Type[] params = ((ParameterizedType) genType).getActualTypeArguments();

        if (index >= params.length || index < 0) {
            log.warn("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: "
                    + params.length);
            return Object.class;
        }
        if (!(params[index] instanceof Class)) {
            log.warn(clazz.getSimpleName() + " not set the actual class on superclass generic parameter");
            return Object.class;
        }
        return (Class) params[index];
    }
}


BeanUtils.java


package com.demonstration.hibernate.dao.support;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;

/**
 * 擴(kuò)展Apache Commons BeanUtils, 提供一些反射方面缺失功能的封裝.
 * @author springside
 * 
 */
public class BeanUtils extends org.apache.commons.beanutils.BeanUtils {

    protected static final Log logger = LogFactory.getLog(BeanUtils.class);

    private BeanUtils() {
    }

    /**
     * 循環(huán)向上轉(zhuǎn)型,獲取對象的DeclaredField.
     *
     * @throws NoSuchFieldException 如果沒有該Field時(shí)拋出.
     */
    public static Field getDeclaredField(Object object, String propertyName) throws NoSuchFieldException {
        Assert.notNull(object);
        Assert.hasText(propertyName);
        return getDeclaredField(object.getClass(), propertyName);
    }

    /**
     * 循環(huán)向上轉(zhuǎn)型,獲取對象的DeclaredField.
     *
     * @throws NoSuchFieldException 如果沒有該Field時(shí)拋出.
     */
    @SuppressWarnings("unchecked")
    public static Field getDeclaredField(Class clazz, String propertyName) throws NoSuchFieldException {
        Assert.notNull(clazz);
        Assert.hasText(propertyName);
        for (Class superClass = clazz; superClass != Object.class; superClass = superClass.getSuperclass()) {
            try {
                return superClass.getDeclaredField(propertyName);
            } catch (NoSuchFieldException e) {
                // Field不在當(dāng)前類定義,繼續(xù)向上轉(zhuǎn)型
            }
        }
        throw new NoSuchFieldException("No such field: " + clazz.getName() + '.' + propertyName);
    }

    /**
     * 暴力獲取對象變量值,忽略private,protected修飾符的限制.
     *
     * @throws NoSuchFieldException 如果沒有該Field時(shí)拋出.
     */
    public static Object forceGetProperty(Object object, String propertyName) throws NoSuchFieldException {
        Assert.notNull(object);
        Assert.hasText(propertyName);

        Field field = getDeclaredField(object, propertyName);

        boolean accessible = field.isAccessible();
        field.setAccessible(true);

        Object result = null;
        try {
            result = field.get(object);
        } catch (IllegalAccessException e) {
            logger.info("error wont' happen");
        }
        field.setAccessible(accessible);
        return result;
    }

    /**
     * 暴力設(shè)置對象變量值,忽略private,protected修飾符的限制.
     *
     * @throws NoSuchFieldException 如果沒有該Field時(shí)拋出.
     */
    public static void forceSetProperty(Object object, String propertyName, Object newValue)
            throws NoSuchFieldException {
        Assert.notNull(object);
        Assert.hasText(propertyName);

        Field field = getDeclaredField(object, propertyName);
        boolean accessible = field.isAccessible();
        field.setAccessible(true);
        try {
            field.set(object, newValue);
        } catch (IllegalAccessException e) {
            logger.info("Error won't happen");
        }
        field.setAccessible(accessible);
    }

    /**
     * 暴力調(diào)用對象函數(shù),忽略private,protected修飾符的限制.
     *
     * @throws NoSuchMethodException 如果沒有該Method時(shí)拋出.
     */
    @SuppressWarnings("unchecked")
    public static Object invokePrivateMethod(Object object, String methodName, Object... params)
            throws NoSuchMethodException {
        Assert.notNull(object);
        Assert.hasText(methodName);
        Class[] types = new Class[params.length];
        for (int i = 0; i < params.length; i++) {
            types[i] = params[i].getClass();
        }

        Class clazz = object.getClass();
        Method method = null;
        for (Class superClass = clazz; superClass != Object.class; superClass = superClass.getSuperclass()) {
            try {
                method = superClass.getDeclaredMethod(methodName, types);
                break;
            } catch (NoSuchMethodException e) {
                // 方法不在當(dāng)前類定義,繼續(xù)向上轉(zhuǎn)型
            }
        }

        if (method == null)
            throw new NoSuchMethodException("No Such Method:" + clazz.getSimpleName() + methodName);

        boolean accessible = method.isAccessible();
        method.setAccessible(true);
        Object result = null;
        try {
            result = method.invoke(object, params);
        } catch (Exception e) {
            ReflectionUtils.handleReflectionException(e);
        }
        method.setAccessible(accessible);
        return result;
    }

    /**
     * 按Filed的類型取得Field列表.
     */
    @SuppressWarnings("unchecked")
    public static List<Field> getFieldsByType(Object object, Class type) {
        List<Field> list = new ArrayList<Field>();
        Field[] fields = object.getClass().getDeclaredFields();
        for (Field field : fields) {
            if (field.getType().isAssignableFrom(type)) {
                list.add(field);
            }
        }
        return list;
    }

    /**
     * 按FiledName獲得Field的類型.
     */
    @SuppressWarnings("unchecked")
    public static Class getPropertyType(Class type, String name) throws NoSuchFieldException {
        return getDeclaredField(type, name).getType();
    }

    /**
     * 獲得field的getter函數(shù)名稱.
     */
    @SuppressWarnings("unchecked")
    public static String getGetterName(Class type, String fieldName) {
        Assert.notNull(type, "Type required");
        Assert.hasText(fieldName, "FieldName required");

        if (type.getName().equals("boolean")) {
            return "is" + StringUtils.capitalize(fieldName);
        } else {
            return "get" + StringUtils.capitalize(fieldName);
        }
    }

    /**
     * 獲得field的getter函數(shù),如果找不到該方法,返回null.
     */
    @SuppressWarnings("unchecked")
    public static Method getGetterMethod(Class type, String fieldName) {
        try {
            return type.getMethod(getGetterName(type, fieldName));
        } catch (NoSuchMethodException e) {
            logger.error(e.getMessage(), e);
        }
        return null;
    }
}


IUndeleteableEntityOperation.java


package com.demonstration.hibernate.dao.extend;

import java.util.List;

import org.hibernate.criterion.Criterion;

/**
 * 定義如果支持Entity不被直接刪除必須支持的Operation.
 *
 * @author springside
 * 
 */
public interface IUndeleteableEntityOperation<T> {
    /*
     * Undelete Entity用到的幾個(gè)常量,因?yàn)橐瑫r(shí)兼顧Interface與Annotation,所以集中放此.
     */
    String UNVALID_VALUE = "-1";

    String NORMAL_VALUE = "0";

    String STATUS = "status";

    /**
     * 取得所有狀態(tài)為有效的對象.
     */
    List<T> getAllValid();

    /**
     * 刪除對象,但如果是Undeleteable的entity,設(shè)置對象的狀態(tài)而不是直接刪除.
     */
    void remove(Object entity);

    /**
     * 獲取過濾已刪除對象的hql條件語句.
     */
    String getUnDeletableHQL();
    /**
     * 獲取過濾已刪除對象的Criterion條件語句.
     */
    Criterion getUnDeletableCriterion();
}


IUndeletableEntity.java

package com.demonstration.hibernate.dao.extend;

/**
 * 標(biāo)識商業(yè)對象不能被刪除,只能被設(shè)為無效的接口.
 *
 * @author springside
 * 
 */
public interface IUndeletableEntity {
    void setStatus(String status);
}


IUndeletable.java

package com.demonstration.hibernate.dao.extend;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 標(biāo)識商業(yè)對象不能被刪除,只能被設(shè)為無效的Annoation.
 * <p/>
 * 相比inferface的標(biāo)示方式,annotation 方式更少侵入性,可以定義任意屬性代表status,而默認(rèn)為status屬性.
 */
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface IUndeletable {
    String status() default IUndeleteableEntityOperation.STATUS;
}


HibernateEntityExtendDao.java

package com.demonstration.hibernate.dao.extend;

import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.PropertyUtils;
import org.hibernate.Criteria;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Restrictions;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;

import com.demonstration.hibernate.dao.HibernateEntityDao;


/**
 * 加強(qiáng)版的entity dao.
 * <p>自動(dòng)處理Undeletable Entity.<br>
 * Undeletable Entity 在刪除時(shí)只把狀態(tài)設(shè)為無效,不會(huì)真正執(zhí)行刪除.<br>
 * Undeletable Entity 可以通過annotation或接口兩種形式來聲明.<br>
 * 其中annotation模式不限制狀態(tài)列的屬性名必須為"status",可以用注釋來確定任意屬性為狀態(tài)屬性.<br>
 * </p>
 *
 * @author springside
 *
 * @see HibernateEntityDao
 * @see EntityInfo
 * @see IUndeleteableEntityOperation
 * @see IUndeletable
 * @see IUndeletableEntity
 */
@SuppressWarnings("unchecked")
public class HibernateEntityExtendDao<T> extends HibernateEntityDao<T> implements IUndeleteableEntityOperation<T> {
    /**
     * 保存所管理的Entity的信息.
     */
    protected EntityInfo entityInfo;

    /**
     * 構(gòu)造函數(shù),初始化entity信息.
     */
    public HibernateEntityExtendDao() {
        entityInfo = new EntityInfo(entityClass);
    }

    /**
     * 取得所有狀態(tài)為有效的對象.
     *
     * @see IUndeleteableEntityOperation#getAllValid()
     */
    public List<T> getAllValid() {
        Criteria criteria = createCriteria();
        if (entityInfo.isUndeletable)
            criteria.add(getUnDeletableCriterion());
        return criteria.list();
    }

    /**
     * 獲取過濾已刪除對象的hql條件語句.
     *
     * @see IUndeleteableEntityOperation#getUnDeletableHQL()
     */
    public String getUnDeletableHQL() {
        return entityInfo.statusProperty + "<>" + UNVALID_VALUE;
    }

    /**
     * 獲取過濾已刪除對象的Criterion條件語句.
     *
     * @see UndeleteableEntityOperation#
     */
    public Criterion getUnDeletableCriterion() {
        return Restrictions.not(Restrictions.eq(entityInfo.statusProperty, UNVALID_VALUE));
    }

    /**
     * 重載保存函數(shù),在保存前先調(diào)用onValid(T),進(jìn)行書名不重復(fù)等數(shù)據(jù)庫相關(guān)的校驗(yàn).
     *
     * @see #onValid(Object)
     * @see HibernateEntityDao#save(Object)
     */
    @Override
    public void save(Object entity) {
        Assert.isInstanceOf(getEntityClass(), entity);
        onValid((T) entity);
        super.save(entity);
    }

    /**
     * 刪除對象,如果是Undeleteable的entity,設(shè)置對象的狀態(tài)而不是直接刪除.
     *
     * @see HibernateEntityDao#remove(Object)
     */
    @Override
    public void remove(Object entity) {
        if (entityInfo.isUndeletable) {
            try {
                PropertyUtils.setProperty(entity, entityInfo.statusProperty, UNVALID_VALUE);
                save(entity);
            } catch (Exception e) {
                ReflectionUtils.handleReflectionException(e);
            }
        } else
            super.remove(entity);
    }

    /**
     * 與數(shù)據(jù)庫相關(guān)的校驗(yàn),比如判斷名字在數(shù)據(jù)庫里有沒有重復(fù), 在保存時(shí)被調(diào)用,在子類重載.
     *
     * @see #save(Object)
     */
    public void onValid(T entity) {
    }

    /**
     * 根據(jù)Map中的條件的Criteria查詢.
     *
     * @param map Map中僅包含條件名與條件值,默認(rèn)全部相同,可重載。
     */
    public List<T> find(Map map) {
        Criteria criteria = createCriteria();
        return find(criteria, map);
    }

    /**
     * 根據(jù)Map中的條件的Criteria查詢.
     *
     * @param map Map中僅包含條件名與條件值,默認(rèn)全部相同,可重載.
     */
    public List<T> find(Criteria criteria, Map map) {
        Assert.notNull(criteria);
        criteria.add(Restrictions.allEq(map));
        return criteria.list();
    }
}


EntityInfo.java
package com.demonstration.hibernate.dao.extend;

/**
 * 裝載Entity信息的內(nèi)部類.
 *
 * @author springside
 * 
 */
class EntityInfo {
    boolean isUndeletable = false; // entity是否undeleteable的標(biāo)志

    String statusProperty; // 標(biāo)識狀態(tài)的屬性名

    @SuppressWarnings("unchecked")
    public EntityInfo(Class entityClass) {
        init(entityClass);
    }

    /**
     * 初始函數(shù),判斷EntityClass是否UndeletableEntity.
     */
    @SuppressWarnings("unchecked")
    private void init(Class entityClass) {
        // 通過EntityClass的interface判斷entity是否undeletable
        if (IUndeletableEntity.class.isAssignableFrom(entityClass)) {
            isUndeletable = true;
            statusProperty = IUndeleteableEntityOperation.STATUS;
        }

        // 通過EntityClass的annotation判斷entity是否undeletable
        if (entityClass.isAnnotationPresent(IUndeletable.class)) {
            isUndeletable = true;
            IUndeletable anno = (IUndeletable) entityClass.getAnnotation(IUndeletable.class);
            statusProperty = anno.status();
        }
    }
}


IEntityDao.java
package com.demonstration.hibernate.dao;

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

/**
 * 針對單個(gè)Entity對象的操作定義.不依賴于具體ORM實(shí)現(xiàn)方案.
 *
 * @author springside
 *
 */
public interface IEntityDao<T> {

    T get(Serializable id);

    List<T> getAll();

    void save(Object o);

    void remove(Object o);

    void removeById(Serializable id);

    /**
     * 獲取Entity對象的主鍵名.
     */
    @SuppressWarnings("unchecked")
    String getIdName(Class clazz);
}


HibernateGenericDao.java
package com.demonstration.hibernate.dao;

import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.beanutils.PropertyUtils;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.DetachedCriteria;
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.metadata.ClassMetadata;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;

import com.demonstration.hibernate.dao.support.BeanUtils;
import com.demonstration.hibernate.dao.support.Page;


/**
 * Hibernate Dao的泛型基類.
 * <p/>
 * 繼承于Spring的<code>HibernateDaoSupport</code>,提供分頁函數(shù)和若干便捷查詢方法,并對返回值作了泛型類型轉(zhuǎn)換.
 *
 * @author springside
 * 
 * @see HibernateDaoSupport
 * @see HibernateEntityDao
 */
@SuppressWarnings("unchecked")
public class HibernateGenericDao extends HibernateDaoSupport {
    /**
     * 根據(jù)ID獲取對象. 實(shí)際調(diào)用Hibernate的session.load()方法返回實(shí)體或其proxy對象. 如果對象不存在,拋出異常.
     */
    public <T> T get(Class<T> entityClass, Serializable id) {
        return (T) getHibernateTemplate().load(entityClass, id);
    }

    /**
     * 獲取全部對象.
     */
    public <T> List<T> getAll(Class<T> entityClass) {
        return getHibernateTemplate().loadAll(entityClass);
    }

    /**
     * 獲取全部對象,帶排序字段與升降序參數(shù).
     */
    public <T> List<T> getAll(Class<T> entityClass, String orderBy, boolean isAsc) {
        Assert.hasText(orderBy);
        if (isAsc)
            return getHibernateTemplate().findByCriteria(
                    DetachedCriteria.forClass(entityClass).addOrder(Order.asc(orderBy)));
        else
            return getHibernateTemplate().findByCriteria(
                    DetachedCriteria.forClass(entityClass).addOrder(Order.desc(orderBy)));
    }

    /**
     * 保存對象.
     */
    public void save(Object o) {
        getHibernateTemplate().saveOrUpdate(o);
    }

    /**
     * 刪除對象.
     */
    public void remove(Object o) {
        getHibernateTemplate().delete(o);
    }

    /**
     * 根據(jù)ID刪除對象.
     */
    public <T> void removeById(Class<T> entityClass, Serializable id) {
        remove(get(entityClass, id));
    }

    public void flush() {
        getHibernateTemplate().flush();
    }

    public void clear() {
        getHibernateTemplate().clear();
    }

    /**
     * 創(chuàng)建Query對象. 對于需要first,max,fetchsize,cache,cacheRegion等諸多設(shè)置的函數(shù),可以在返回Query后自行設(shè)置.
     * 留意可以連續(xù)設(shè)置,如下:
     * <pre>
     * dao.getQuery(hql).setMaxResult(100).setCacheable(true).list();
     * </pre>
     * 調(diào)用方式如下:
     * <pre>
     *        dao.createQuery(hql)
     *        dao.createQuery(hql,arg0);
     *        dao.createQuery(hql,arg0,arg1);
     *        dao.createQuery(hql,new Object[arg0,arg1,arg2])
     * </pre>
     *
     * @param values 可變參數(shù).
     */
    public Query createQuery(String hql, Object... values) {
        Assert.hasText(hql);
        Query query = getSession().createQuery(hql);
        for (int i = 0; i < values.length; i++) {
            query.setParameter(i, values[i]);
        }
        return query;
    }

    /**
     * 創(chuàng)建Criteria對象.
     *
     * @param criterions 可變的Restrictions條件列表,見{@link #createQuery(String,Object...)}
     */
    public <T> Criteria createCriteria(Class<T> entityClass, Criterion... criterions) {
        Criteria criteria = getSession().createCriteria(entityClass);
        for (Criterion c : criterions) {
            criteria.add(c);
        }
        return criteria;
    }

    /**
     * 創(chuàng)建Criteria對象,帶排序字段與升降序字段.
     *
     * @see #createCriteria(Class,Criterion[])
     */
    public <T> Criteria createCriteria(Class<T> entityClass, String orderBy, boolean isAsc, Criterion... criterions) {
        Assert.hasText(orderBy);

        Criteria criteria = createCriteria(entityClass, criterions);

        if (isAsc)
            criteria.addOrder(Order.asc(orderBy));
        else
            criteria.addOrder(Order.desc(orderBy));

        return criteria;
    }

    /**
     * 根據(jù)hql查詢,直接使用HibernateTemplate的find函數(shù).
     *
     * @param values 可變參數(shù),見{@link #createQuery(String,Object...)}
     */
    public List find(String hql, Object... values) {
        Assert.hasText(hql);
        return getHibernateTemplate().find(hql, values);
    }

    /**
     * 根據(jù)屬性名和屬性值查詢對象.
     *
     * @return 符合條件的對象列表
     */
    public <T> List<T> findBy(Class<T> entityClass, String propertyName, Object value) {
        Assert.hasText(propertyName);
        return createCriteria(entityClass, Restrictions.eq(propertyName, value)).list();
    }

    /**
     * 根據(jù)屬性名和屬性值查詢對象,帶排序參數(shù).
     */
    public <T> List<T> findBy(Class<T> entityClass, String propertyName, Object value, String orderBy, boolean isAsc) {
        Assert.hasText(propertyName);
        Assert.hasText(orderBy);
        return createCriteria(entityClass, orderBy, isAsc, Restrictions.eq(propertyName, value)).list();
    }

    /**
     * 根據(jù)屬性名和屬性值查詢唯一對象.
     *
     * @return 符合條件的唯一對象 or null if not found.
     */
    public <T> T findUniqueBy(Class<T> entityClass, String propertyName, Object value) {
        Assert.hasText(propertyName);
        return (T) createCriteria(entityClass, Restrictions.eq(propertyName, value)).uniqueResult();
    }

    /**
     * 分頁查詢函數(shù),使用hql.
     *
     * @param pageNo 頁號,從1開始.
     */
    public Page pagedQuery(String hql, int pageNo, int pageSize, Object... values) {
        Assert.hasText(hql);
        Assert.isTrue(pageNo >= 1, "pageNo should start from 1");
        // Count查詢
        String countQueryString = " select count (*) " + removeSelect(removeOrders(hql));
        List countlist = getHibernateTemplate().find(countQueryString, values);
        long totalCount = (Long) countlist.get(0);

        if (totalCount < 1)
            return new Page();
        // 實(shí)際查詢返回分頁對象
        int startIndex = Page.getStartOfPage(pageNo, pageSize);
        Query query = createQuery(hql, values);
        List list = query.setFirstResult(startIndex).setMaxResults(pageSize).list();

        return new Page(startIndex, totalCount, pageSize, list);
    }
    
     /**
     * @author Scott.wanglei
     * @since  2008-7-21
     * @param hql 查詢sql
     * @param start 分頁從哪一條數(shù)據(jù)開始
     * @param pageSize 每一個(gè)頁面的大小
     * @param values 查詢條件
     * @return page對象
     */
    public Page dataQuery(String hql, int start, int pageSize, Object... values){
        // Count查詢
        String countQueryString = " select count (*) " + removeSelect(removeOrders(hql));
        List countlist = getHibernateTemplate().find(countQueryString, values);
        long totalCount = (Long) countlist.get(0);

        if (totalCount < 1)
            return new Page();
        // 實(shí)際查詢返回分頁對象
        int startIndex = start;
        Query query = createQuery(hql, values);
        List list = query.setFirstResult(startIndex).setMaxResults(pageSize).list();

        return new Page(startIndex, totalCount, pageSize, list);
     }
    /**
     * 分頁查詢函數(shù),使用已設(shè)好查詢條件與排序的<code>Criteria</code>.
     *
     * @param pageNo 頁號,從1開始.
     * @return 含總記錄數(shù)和當(dāng)前頁數(shù)據(jù)的Page對象.
     */
    public Page pagedQuery(Criteria criteria, int pageNo, int pageSize) {
        Assert.notNull(criteria);
        Assert.isTrue(pageNo >= 1, "pageNo should start from 1");
        CriteriaImpl impl = (CriteriaImpl) criteria;

        // 先把Projection和OrderBy條件取出來,清空兩者來執(zhí)行Count操作
        Projection projection = impl.getProjection();
        List<CriteriaImpl.OrderEntry> orderEntries;
        try {
            orderEntries = (List) BeanUtils.forceGetProperty(impl, "orderEntries");
            BeanUtils.forceSetProperty(impl, "orderEntries", new ArrayList());
        } catch (Exception e) {
            throw new InternalError(" Runtime Exception impossibility throw ");
        }

        // 執(zhí)行查詢
        int totalCount = (Integer) criteria.setProjection(Projections.rowCount()).uniqueResult();

        // 將之前的Projection和OrderBy條件重新設(shè)回去
        criteria.setProjection(projection);
        if (projection == null) {
            criteria.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);
        }

        try {
            BeanUtils.forceSetProperty(impl, "orderEntries", orderEntries);
        } catch (Exception e) {
            throw new InternalError(" Runtime Exception impossibility throw ");
        }

        // 返回分頁對象
        if (totalCount < 1)
            return new Page();

        int startIndex = Page.getStartOfPage(pageNo, pageSize);;
        List list = criteria.setFirstResult(startIndex).setMaxResults(pageSize).list();
        return new Page(startIndex, totalCount, pageSize, list);
    }

    /**
     * 分頁查詢函數(shù),根據(jù)entityClass和查詢條件參數(shù)創(chuàng)建默認(rèn)的<code>Criteria</code>.
     *
     * @param pageNo 頁號,從1開始.
     * @return 含總記錄數(shù)和當(dāng)前頁數(shù)據(jù)的Page對象.
     */
    public Page pagedQuery(Class entityClass, int pageNo, int pageSize, Criterion... criterions) {
        Criteria criteria = createCriteria(entityClass, criterions);
        return pagedQuery(criteria, pageNo, pageSize);
    }

    /**
     * 分頁查詢函數(shù),根據(jù)entityClass和查詢條件參數(shù),排序參數(shù)創(chuàng)建默認(rèn)的<code>Criteria</code>.
     *
     * @param pageNo 頁號,從1開始.
     * @return 含總記錄數(shù)和當(dāng)前頁數(shù)據(jù)的Page對象.
     */
    public Page pagedQuery(Class entityClass, int pageNo, int pageSize, String orderBy, boolean isAsc,
                           Criterion... criterions) {
        Criteria criteria = createCriteria(entityClass, orderBy, isAsc, criterions);
        return pagedQuery(criteria, pageNo, pageSize);
    }

    /**
     * 判斷對象某些屬性的值在數(shù)據(jù)庫中是否唯一.
     *
     * @param uniquePropertyNames 在POJO里不能重復(fù)的屬性列表,以逗號分割 如"name,loginid,password"
     */
    public <T> boolean isUnique(Class<T> entityClass, Object entity, String uniquePropertyNames) {
        Assert.hasText(uniquePropertyNames);
        Criteria criteria = createCriteria(entityClass).setProjection(Projections.rowCount());
        String[] nameList = uniquePropertyNames.split(",");
        try {
            // 循環(huán)加入唯一列
            for (String name : nameList) {
                criteria.add(Restrictions.eq(name, PropertyUtils.getProperty(entity, name)));
            }

            // 以下代碼為了如果是update的情況,排除entity自身.

            String idName = getIdName(entityClass);

            // 取得entity的主鍵值
            Serializable id = getId(entityClass, entity);

            // 如果id!=null,說明對象已存在,該操作為update,加入排除自身的判斷
            if (id != null)
                criteria.add(Restrictions.not(Restrictions.eq(idName, id)));
        } catch (Exception e) {
            ReflectionUtils.handleReflectionException(e);
        }
        return (Integer) criteria.uniqueResult() == 0;
    }

    /**
     * 取得對象的主鍵值,輔助函數(shù).
     */
    public Serializable getId(Class entityClass, Object entity) throws NoSuchMethodException, IllegalAccessException,
            InvocationTargetException {
        Assert.notNull(entity);
        Assert.notNull(entityClass);
        return (Serializable) PropertyUtils.getProperty(entity, getIdName(entityClass));
    }

    /**
     * 取得對象的主鍵名,輔助函數(shù).
     */
    public String getIdName(Class clazz) {
        Assert.notNull(clazz);
        ClassMetadata meta = getSessionFactory().getClassMetadata(clazz);
        Assert.notNull(meta, "Class " + clazz + " not define in hibernate session factory.");
        String idName = meta.getIdentifierPropertyName();
        Assert.hasText(idName, clazz.getSimpleName() + " has no identifier property define.");
        return idName;
    }

    /**
     * 去除hql的select 子句,未考慮union的情況,用于pagedQuery.
     *
     * @see #pagedQuery(String,int,int,Object[])
     */
    private static String removeSelect(String hql) {
        Assert.hasText(hql);
        int beginPos = hql.toLowerCase().indexOf("from");
        Assert.isTrue(beginPos != -1, " hql : " + hql + " must has a keyword 'from'");
        return hql.substring(beginPos);
    }

    /**
     * 去除hql的orderby 子句,用于pagedQuery.
     *
     * @see #pagedQuery(String,int,int,Object[])
     */
    private static String removeOrders(String hql) {
        Assert.hasText(hql);
        Pattern p = Pattern.compile("order\\s*by[\\w|\\W|\\s|\\S]*", Pattern.CASE_INSENSITIVE);
        Matcher m = p.matcher(hql);
        StringBuffer sb = new StringBuffer();
        while (m.find()) {
            m.appendReplacement(sb, "");
        }
        m.appendTail(sb);
        return sb.toString();
    }
    
}
HibernateEntityDao.java
package com.demonstration.hibernate.dao;

import java.io.Serializable;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.criterion.Criterion;

import com.demonstration.hibernate.dao.support.GenericsUtils;

/**
 * 負(fù)責(zé)為單個(gè)Entity對象提供CRUD操作的Hibernate DAO基類. <p/> 子類只要在類定義時(shí)指定所管理Entity的Class,
 * 即擁有對單個(gè)Entity對象的CRUD操作.
 * 
 * <pre>
 * public class UserManager extends HibernateEntityDao<User> {
 * }
 * </pre>
 * 
 * @author springside
 * 
 * @see HibernateGenericDao
 */
@SuppressWarnings("unchecked")
public class HibernateEntityDao<T> extends HibernateGenericDao implements
        IEntityDao<T> {

    protected Class<T> entityClass;// DAO所管理的Entity類型.

    /**
     * 在構(gòu)造函數(shù)中將泛型T.class賦給entityClass.
     */
    public HibernateEntityDao() {
        entityClass = GenericsUtils.getSuperClassGenricType(getClass());
    }

    /**
     * 重載構(gòu)造函數(shù) 讓spring提供構(gòu)造函數(shù)注入
     */
    public HibernateEntityDao(Class<T> type) {
        this.entityClass = type;
    }
    
    /**
     * 取得entityClass.JDK1.4不支持泛型的子類可以拋開Class<T> entityClass,重載此函數(shù)達(dá)到相同效果。
     */
    protected Class<T> getEntityClass() {
        return entityClass;
    }
    
    public void setEntityClass(Class<T> type){
        this.entityClass=type;
    }

    /**
     * 根據(jù)ID獲取對象.
     * 
     * @see HibernateGenericDao#getId(Class,Object)
     */
    public T get(Serializable id) {
        return get(getEntityClass(), id);
    }

    /**
     * 獲取全部對象
     * 
     * @see HibernateGenericDao#getAll(Class)
     */
    public List<T> getAll() {
        return getAll(getEntityClass());
    }

    /**
     * 獲取全部對象,帶排序參數(shù).
     * 
     * @see HibernateGenericDao#getAll(Class,String,boolean)
     */
    public List<T> getAll(String orderBy, boolean isAsc) {
        return getAll(getEntityClass(), orderBy, isAsc);
    }

    /**
     * 根據(jù)ID移除對象.
     * 
     * @see HibernateGenericDao#removeById(Class,Serializable)
     */
    public void removeById(Serializable id) {
        removeById(getEntityClass(), id);
    }

    /**
     * 取得Entity的Criteria.
     * 
     * @see HibernateGenericDao#createCriteria(Class,Criterion[])
     */
    public Criteria createCriteria(Criterion... criterions) {
        return createCriteria(getEntityClass(), criterions);
    }

    /**
     * 取得Entity的Criteria,帶排序參數(shù).
     * 
     * @see HibernateGenericDao#createCriteria(Class,String,boolean,Criterion[])
     */
    public Criteria createCriteria(String orderBy, boolean isAsc,
            Criterion... criterions) {
        return createCriteria(getEntityClass(), orderBy, isAsc, criterions);
    }

    /**
     * 根據(jù)屬性名和屬性值查詢對象.
     * 
     * @return 符合條件的對象列表
     * @see HibernateGenericDao#findBy(Class,String,Object)
     */
    public List<T> findBy(String propertyName, Object value) {
        return findBy(getEntityClass(), propertyName, value);
    }

    /**
     * 根據(jù)屬性名和屬性值查詢對象,帶排序參數(shù).
     * 
     * @return 符合條件的對象列表
     * @see HibernateGenericDao#findBy(Class,String,Object,String,boolean)
     */
    public List<T> findBy(String propertyName, Object value, String orderBy,
            boolean isAsc) {
        return findBy(getEntityClass(), propertyName, value, orderBy, isAsc);
    }

    /**
     * 根據(jù)屬性名和屬性值查詢單個(gè)對象.
     * 
     * @return 符合條件的唯一對象 or null
     * @see HibernateGenericDao#findUniqueBy(Class,String,Object)
     */
    public T findUniqueBy(String propertyName, Object value) {
        return findUniqueBy(getEntityClass(), propertyName, value);
    }

    /**
     * 判斷對象某些屬性的值在數(shù)據(jù)庫中唯一.
     * 
     * @param uniquePropertyNames
     *            在POJO里不能重復(fù)的屬性列表,以逗號分割 如"name,loginid,password"
     * @see HibernateGenericDao#isUnique(Class,Object,String)
     */
    public boolean isUnique(Object entity, String uniquePropertyNames) {
        return isUnique(getEntityClass(), entity, uniquePropertyNames);
    }

    /**
     * 消除與 Hibernate Session 的關(guān)聯(lián)
     * 
     * @param entity
     */
    public void evit(Object entity) {
        getHibernateTemplate().evict(entity);
    }
}


IBaseDao.java
/**
 * 
 */
package com.demonstration.hibernate.basedao;

import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Map;

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

import com.demonstration.hibernate.dao.HibernateEntityDao;
import com.demonstration.hibernate.dao.HibernateGenericDao;
import com.demonstration.hibernate.dao.extend.IUndeleteableEntityOperation;
import com.demonstration.hibernate.dao.support.Page;


/**
 * @author 
 * 
 * 提供hibernate dao的所有操作,
 * 實(shí)現(xiàn)類由spring注入HibernateEntityDao和HibernateEntityExtendDao來實(shí)現(xiàn)
 * 最大限度的解耦hibernate持久層的操作
 */
public interface IBaseDao<T> {

    /**
     * 根據(jù)ID獲取對象.
     * 
     * @see HibernateGenericDao#getId(Class,Object)
     */
    public T get(Serializable id);
    
    /**
     * 獲取全部對象
     * 
     * @see HibernateGenericDao#getAll(Class)
     */
    public List<T> getAll();
    
    /**
     * 獲取全部對象,帶排序參數(shù).
     * 
     * @see HibernateGenericDao#getAll(Class,String,boolean)
     */
    public List<T> getAll(String orderBy, boolean isAsc);
    
    /**
     * 根據(jù)ID移除對象.
     * 
     * @see HibernateGenericDao#removeById(Class,Serializable)
     */
    public void removeById(Serializable id);
    
    /**
     * 取得Entity的Criteria.
     * 
     * @see HibernateGenericDao#createCriteria(Class,Criterion[])
     */
    public Criteria createCriteria(Criterion... criterions);
    
    /**
     * 取得Entity的Criteria,帶排序參數(shù).
     * 
     * @see HibernateGenericDao#createCriteria(Class,String,boolean,Criterion[])
     */
    public Criteria createCriteria(String orderBy, boolean isAsc,
            Criterion... criterions);
    
    /**
     * 根據(jù)屬性名和屬性值查詢對象.
     * 
     * @return 符合條件的對象列表
     * @see HibernateGenericDao#findBy(Class,String,Object)
     */
    public List<T> findBy(String propertyName, Object value);
    
    /**
     * 根據(jù)屬性名和屬性值查詢對象,帶排序參數(shù).
     * 
     * @return 符合條件的對象列表
     * @see HibernateGenericDao#findBy(Class,String,Object,String,boolean)
     */
    public List<T> findBy(String propertyName, Object value, String orderBy,
            boolean isAsc);
    
    /**
     * 根據(jù)屬性名和屬性值查詢單個(gè)對象.
     * 
     * @return 符合條件的唯一對象 or null
     * @see HibernateGenericDao#findUniqueBy(Class,String,Object)
     */
    public T findUniqueBy(String propertyName, Object value);
    
    /**
     * 判斷對象某些屬性的值在數(shù)據(jù)庫中唯一.
     * 
     * @param uniquePropertyNames
     *            在POJO里不能重復(fù)的屬性列表,以逗號分割 如"name,loginid,password"
     * @see HibernateGenericDao#isUnique(Class,Object,String)
     */
    public boolean isUnique(Object entity, String uniquePropertyNames);
    
    /**
     * 消除與 Hibernate Session 的關(guān)聯(lián)
     * 
     * @param entity
     */
    public void evit(Object entity);
    
    /*******************************************************************************************/
    
    /**
     * 取得所有狀態(tài)為有效的對象.
     *
     * @see IUndeleteableEntityOperation#getAllValid()
     */
    public List<T> getAllValid();
    
    /**
     * 獲取過濾已刪除對象的hql條件語句.
     *
     * @see IUndeleteableEntityOperation#getUnDeletableHQL()
     */
    public String getUnDeletableHQL();
    
    /**
     * 獲取過濾已刪除對象的Criterion條件語句.
     *
     * @see UndeleteableEntityOperation#
     */
    public Criterion getUnDeletableCriterion();
    
    /**
     * 重載保存函數(shù),在保存前先調(diào)用onValid(T),進(jìn)行書名不重復(fù)等數(shù)據(jù)庫相關(guān)的校驗(yàn).
     *
     * @see #onValid(Object)
     * @see HibernateEntityDao#save(Object)
     */
    public void saveOnValid(Object entity);
    
    /**
     * 刪除對象,如果是Undeleteable的entity,設(shè)置對象的狀態(tài)而不是直接刪除.
     *
     * @see HibernateEntityDao#remove(Object)
     */
    public void removeUndeleteable(Object entity);
    
    /**
     * 與數(shù)據(jù)庫相關(guān)的校驗(yàn),比如判斷名字在數(shù)據(jù)庫里有沒有重復(fù), 在保存時(shí)被調(diào)用,在子類重載.
     *
     * @see #save(Object)
     */
    public void onValid(T entity);
    
    /**
     * 根據(jù)Map中的條件的Criteria查詢.
     *
     * @param map Map中僅包含條件名與條件值,默認(rèn)全部相同,可重載。
     */
    @SuppressWarnings("unchecked")
    public List<T> find(Map map);
    
    /**
     * 根據(jù)Map中的條件的Criteria查詢.
     *
     * @param map Map中僅包含條件名與條件值,默認(rèn)全部相同,可重載.
     */
    @SuppressWarnings("unchecked")
    public List<T> find(Criteria criteria, Map map);
    
    /*******************************************************************************************/
    
    /**
     * 根據(jù)ID獲取對象. 實(shí)際調(diào)用Hibernate的session.load()方法返回實(shí)體或其proxy對象. 如果對象不存在,拋出異常.
     */
    public T get(Class<T> entityClass, Serializable id);
    
    /**
     * 獲取全部對象.
     */
    public  List<T> getAll(Class<T> entityClass);
    
    /**
     * 獲取全部對象,帶排序字段與升降序參數(shù).
     */
    public  List<T> getAll(Class<T> entityClass, String orderBy, boolean isAsc);
    
    /**
     * 保存對象.
     */
    public void save(Object o);
    
    /**
     * 刪除對象.
     */
    public void remove(Object o);
    
    public void flush();
    
    public void clear();
    
    /**
     * 創(chuàng)建Query對象. 對于需要first,max,fetchsize,cache,cacheRegion等諸多設(shè)置的函數(shù),可以在返回Query后自行設(shè)置.
     * 留意可以連續(xù)設(shè)置,如下:
     * <pre>
     * dao.getQuery(hql).setMaxResult(100).setCacheable(true).list();
     * </pre>
     * 調(diào)用方式如下:
     * <pre>
     *        dao.createQuery(hql)
     *        dao.createQuery(hql,arg0);
     *        dao.createQuery(hql,arg0,arg1);
     *        dao.createQuery(hql,new Object[arg0,arg1,arg2])
     * </pre>
     *
     * @param values 可變參數(shù).
     */
    public Query createQuery(String hql, Object... values);
    
    /**
     * 創(chuàng)建Criteria對象.
     *
     * @param criterions 可變的Restrictions條件列表,見{@link #createQuery(String,Object...)}
     */
    public  Criteria createCriteria(Class<T> entityClass, Criterion... criterions);
    
    /**
     * 創(chuàng)建Criteria對象,帶排序字段與升降序字段.
     *
     * @see #createCriteria(Class,Criterion[])
     */
    public  Criteria createCriteria(Class<T> entityClass, String orderBy, boolean isAsc, Criterion... criterions);
    
    /**
     * 根據(jù)hql查詢,直接使用HibernateTemplate的find函數(shù).
     *
     * @param values 可變參數(shù),見{@link #createQuery(String,Object...)}
     */
    @SuppressWarnings("unchecked")
    public List find(String hql, Object... values);
    
    /**
     * 根據(jù)屬性名和屬性值查詢對象.
     *
     * @return 符合條件的對象列表
     */
    public  List<T> findBy(Class<T> entityClass, String propertyName, Object value);
    
    /**
     * 根據(jù)屬性名和屬性值查詢對象,帶排序參數(shù).
     */
    public  List<T> findBy(Class<T> entityClass, String propertyName, Object value, String orderBy, boolean isAsc);
    
    /**
     * 根據(jù)屬性名和屬性值查詢唯一對象.
     *
     * @return 符合條件的唯一對象 or null if not found.
     */
    public  T findUniqueBy(Class<T> entityClass, String propertyName, Object value);
    
    /**
     * 分頁查詢函數(shù),使用hql.
     *
     * @param pageNo 頁號,從1開始.
     */
    public Page pagedQuery(String hql, int pageNo, int pageSize, Object... values);
    
    /**
     * @author Scott.wanglei
     * @since  2008-7-21
     * @param hql 查詢sql
     * @param start 分頁從哪一條數(shù)據(jù)開始
     * @param pageSize 每一個(gè)頁面的大小
     * @param values 查詢條件
     * @return page對象
     */
    public Page dataQuery(String hql, int start, int pageSize, Object... values);
    
    /**
     * 分頁查詢函數(shù),使用已設(shè)好查詢條件與排序的<code>Criteria</code>.
     *
     * @param pageNo 頁號,從1開始.
     * @return 含總記錄數(shù)和當(dāng)前頁數(shù)據(jù)的Page對象.
     */
    public Page pagedQuery(Criteria criteria, int pageNo, int pageSize);
    
    /**
     * 分頁查詢函數(shù),根據(jù)entityClass和查詢條件參數(shù)創(chuàng)建默認(rèn)的<code>Criteria</code>.
     *
     * @param pageNo 頁號,從1開始.
     * @return 含總記錄數(shù)和當(dāng)前頁數(shù)據(jù)的Page對象.
     */
    @SuppressWarnings("unchecked")
    public Page pagedQuery(Class entityClass, int pageNo, int pageSize, Criterion... criterions);
    
    /**
     * 分頁查詢函數(shù),根據(jù)entityClass和查詢條件參數(shù),排序參數(shù)創(chuàng)建默認(rèn)的<code>Criteria</code>.
     *
     * @param pageNo 頁號,從1開始.
     * @return 含總記錄數(shù)和當(dāng)前頁數(shù)據(jù)的Page對象.
     */
    @SuppressWarnings("unchecked")
    public Page pagedQuery(Class entityClass, int pageNo, int pageSize, String orderBy, boolean isAsc,
               Criterion... criterions);
    
    /**
     * 判斷對象某些屬性的值在數(shù)據(jù)庫中是否唯一.
     *
     * @param uniquePropertyNames 在POJO里不能重復(fù)的屬性列表,以逗號分割 如"name,loginid,password"
     */
    public  boolean isUnique(Class<T> entityClass, Object entity, String uniquePropertyNames);
    
    /**
     * 取得對象的主鍵值,輔助函數(shù).
     */
    @SuppressWarnings("unchecked")
    public Serializable getId(Class entityClass, Object entity) throws NoSuchMethodException, IllegalAccessException,
    InvocationTargetException ;
    
    /**
     * 取得對象的主鍵名,輔助函數(shù).
     */
    @SuppressWarnings("unchecked")
    public String getIdName(Class clazz);
}


BaseDao.java
/**
 * 
 */
package com.demonstration.hibernate.basedao;

import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Map;

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

import com.demonstration.hibernate.dao.HibernateEntityDao;
import com.demonstration.hibernate.dao.HibernateGenericDao;
import com.demonstration.hibernate.dao.extend.HibernateEntityExtendDao;
import com.demonstration.hibernate.dao.extend.IUndeleteableEntityOperation;
import com.demonstration.hibernate.dao.support.Page;

/**
 * @author 
 *
 * IBaseDao的實(shí)現(xiàn)類通過spring注入HibernateEntityDao和HibernateEntityExtendDao來實(shí)現(xiàn)
 */
public class BaseDao<T> implements IBaseDao<T> {

    protected Class<T> entityClass;// DAO所管理的Entity類型.
    private HibernateEntityDao<T> hedao;
    private HibernateEntityExtendDao<T> hexdao;
    
    
    public void setHedao(HibernateEntityDao<T> hedao) {
        hedao.setEntityClass(entityClass);
        this.hedao=hedao;
    }

    public void setHexdao(HibernateEntityExtendDao<T> hexdao) {
        hexdao.setEntityClass(entityClass);
        this.hexdao=hexdao;
    }
    
    /**
     *讓spring提供構(gòu)造函數(shù)注入
     */
    public BaseDao(Class<T> type) {
        this.entityClass = type;
    }
    
    public BaseDao(){}
    /**
     * 根據(jù)ID獲取對象.
     * 
     * @see HibernateGenericDao#getId(Class,Object)
     */
    public T get(Serializable id) {
        return hedao.get(id);
    }

    /**
     * 獲取全部對象
     * 
     * @see HibernateGenericDao#getAll(Class)
     */
    public List<T> getAll() {
        return hedao.getAll();
    }


    /**
     * 獲取全部對象,帶排序參數(shù).
     * 
     * @see HibernateGenericDao#getAll(Class,String,boolean)
     */
    public List<T> getAll(String orderBy, boolean isAsc) {
        return hedao.getAll(orderBy, isAsc);
    }

    /**
     * 根據(jù)ID移除對象.
     * 
     * @see HibernateGenericDao#removeById(Class,Serializable)
     */
    public void removeById(Serializable id) {
        hedao.removeById(id);
    }

    /**
     * 取得Entity的Criteria.
     * 
     * @see HibernateGenericDao#createCriteria(Class,Criterion[])
     */
    public Criteria createCriteria(Criterion... criterions) {
        return hedao.createCriteria(criterions);
    }

    /**
     * 取得Entity的Criteria,帶排序參數(shù).
     * 
     * @see HibernateGenericDao#createCriteria(Class,String,boolean,Criterion[])
     */
    public Criteria createCriteria(String orderBy, boolean isAsc,
            Criterion... criterions) {
        return hedao.createCriteria(orderBy, isAsc, criterions);
    }

    /**
     * 根據(jù)屬性名和屬性值查詢對象.
     * 
     * @return 符合條件的對象列表
     * @see HibernateGenericDao#findBy(Class,String,Object)
     */
    public List<T> findBy(String propertyName, Object value) {
        return hedao.findBy(propertyName, value);
    }

    /**
     * 根據(jù)屬性名和屬性值查詢對象,帶排序參數(shù).
     * 
     * @return 符合條件的對象列表
     * @see HibernateGenericDao#findBy(Class,String,Object,String,boolean)
     */
    public List<T> findBy(String propertyName, Object value, String orderBy,
            boolean isAsc) {
        return hedao.findBy(propertyName, value, orderBy, isAsc);
    }

    /**
     * 根據(jù)屬性名和屬性值查詢單個(gè)對象.
     * 
     * @return 符合條件的唯一對象 or null
     * @see HibernateGenericDao#findUniqueBy(Class,String,Object)
     */
    public T findUniqueBy(String propertyName, Object value) {
        return hedao.findUniqueBy(propertyName, value);
    }

    /**
     * 判斷對象某些屬性的值在數(shù)據(jù)庫中唯一.
     * 
     * @param uniquePropertyNames
     *            在POJO里不能重復(fù)的屬性列表,以逗號分割 如"name,loginid,password"
     * @see HibernateGenericDao#isUnique(Class,Object,String)
     */
    public boolean isUnique(Object entity, String uniquePropertyNames) {
        return hedao.isUnique(entity, uniquePropertyNames);
    }

    /**
     * 消除與 Hibernate Session 的關(guān)聯(lián)
     * 
     * @param entity
     */
    public void evit(Object entity) {
        hedao.evit(entity);
    }

    /**
     * 取得所有狀態(tài)為有效的對象.
     *
     * @see IUndeleteableEntityOperation#getAllValid()
     */
    public List<T> getAllValid() {
        return hexdao.getAllValid();
    }

    /**
     * 獲取過濾已刪除對象的hql條件語句.
     *
     * @see IUndeleteableEntityOperation#getUnDeletableHQL()
     */
    public String getUnDeletableHQL() {
        return hexdao.getUnDeletableHQL();
    }

    /**
     * 獲取過濾已刪除對象的Criterion條件語句.
     *
     * @see UndeleteableEntityOperation#
     */
    public Criterion getUnDeletableCriterion() {
        return hexdao.getUnDeletableCriterion();
    }

    /**
     * 重載保存函數(shù),在保存前先調(diào)用onValid(T),進(jìn)行書名不重復(fù)等數(shù)據(jù)庫相關(guān)的校驗(yàn).
     *
     * @see #onValid(Object)
     * @see HibernateEntityDao#save(Object)
     */
    public void saveOnValid(Object entity) {
         hexdao.save(entity);
    }

    /**
     * 刪除對象,如果是Undeleteable的entity,設(shè)置對象的狀態(tài)而不是直接刪除.
     *
     * @see HibernateEntityDao#remove(Object)
     */
    public void removeUndeleteable(Object entity) {
           hexdao.remove(entity);
    }

    /**
     * 與數(shù)據(jù)庫相關(guān)的校驗(yàn),比如判斷名字在數(shù)據(jù)庫里有沒有重復(fù), 在保存時(shí)被調(diào)用,在此可重寫.
     *
     * @see #save(Object)
     */
    public void onValid(T entity) {
           
    }

    /**
     * 根據(jù)Map中的條件的Criteria查詢.
     *
     * @param map Map中僅包含條件名與條件值,默認(rèn)全部相同,可重載。
     */
    @SuppressWarnings("unchecked")
    public List<T> find(Map map) {
        return hexdao.find(map);
    }

    /**
     * 根據(jù)Map中的條件的Criteria查詢.
     *
     * @param map Map中僅包含條件名與條件值,默認(rèn)全部相同,可重載.
     */
    @SuppressWarnings("unchecked")
    public List<T> find(Criteria criteria, Map map) {
        return hexdao.find(criteria, map);
    }

    /**
     * 根據(jù)ID獲取對象. 實(shí)際調(diào)用Hibernate的session.load()方法返回實(shí)體或其proxy對象. 如果對象不存在,拋出異常.
     */
    public T get(Class<T> entityClass, Serializable id) {
        return hedao.get(entityClass, id);
    }

    /**
     * 獲取全部對象.
     */
    public List<T> getAll(Class<T> entityClass) {
        return hedao.getAll(entityClass);
    }

    /**
     * 獲取全部對象,帶排序字段與升降序參數(shù).
     */
    public List<T> getAll(Class<T> entityClass, String orderBy, boolean isAsc) {    
        return hedao.getAll(entityClass, orderBy, isAsc);
    }

    /**
     * 保存對象.
     */
    public void save(Object o) {
          hedao.save(o);
    }

    /**
     * 刪除對象.
     */
    public void remove(Object o) {
         hedao.remove(o);
    }
    
    public void flush(){
        hedao.flush();
    }
    
    public void clear(){
        hedao.clear();
    }

    /**
     * 創(chuàng)建Query對象. 對于需要first,max,fetchsize,cache,cacheRegion等諸多設(shè)置的函數(shù),可以在返回Query后自行設(shè)置.
     * 留意可以連續(xù)設(shè)置,如下:
     * <pre>
     * dao.getQuery(hql).setMaxResult(100).setCacheable(true).list();
     * </pre>
     * 調(diào)用方式如下:
     * <pre>
     *        dao.createQuery(hql)
     *        dao.createQuery(hql,arg0);
     *        dao.createQuery(hql,arg0,arg1);
     *        dao.createQuery(hql,new Object[arg0,arg1,arg2])
     * </pre>
     *
     * @param values 可變參數(shù).
     */
    public Query createQuery(String hql, Object... values) {
        
        return hedao.createQuery(hql, values);
    }

    /**
     * 創(chuàng)建Criteria對象.
     *
     * @param criterions 可變的Restrictions條件列表,見{@link #createQuery(String,Object...)}
     */
    public Criteria createCriteria(Class<T> entityClass,
            Criterion... criterions) {
        
        return hedao.createCriteria(entityClass, criterions);
    }

    /**
     * 創(chuàng)建Criteria對象,帶排序字段與升降序字段.
     *
     * @see #createCriteria(Class,Criterion[])
     */
    public Criteria createCriteria(Class<T> entityClass, String orderBy,
            boolean isAsc, Criterion... criterions) {
        return hedao.createCriteria(entityClass, orderBy, isAsc, criterions);
    }

    /**
     * 根據(jù)hql查詢,直接使用HibernateTemplate的find函數(shù).
     *
     * @param values 可變參數(shù),見{@link #createQuery(String,Object...)}
     */
    @SuppressWarnings("unchecked")
    public List find(String hql, Object... values) {
        return hedao.find(hql, values);
    }

    /**
     * 根據(jù)屬性名和屬性值查詢對象.
     *
     * @return 符合條件的對象列表
     */
    public  List<T> findBy(Class<T> entityClass, String propertyName,
            Object value) {
        
        return hedao.findBy(entityClass, propertyName, value);
    }

    /**
     * 根據(jù)屬性名和屬性值查詢對象,帶排序參數(shù).
     */
    public List<T> findBy(Class<T> entityClass, String propertyName,
            Object value, String orderBy, boolean isAsc) {
        return hedao.findBy(entityClass, propertyName, value, orderBy, isAsc);
    }

    /**
     * 根據(jù)屬性名和屬性值查詢唯一對象.
     *
     * @return 符合條件的唯一對象 or null if not found.
     */
    public T findUniqueBy(Class<T> entityClass, String propertyName,
            Object value) {
        return hedao.findUniqueBy(propertyName, value);
    }

    /**
     * 分頁查詢函數(shù),使用hql.
     *
     * @param pageNo 頁號,從1開始.
     */
    public Page pagedQuery(String hql, int pageNo, int pageSize,
            Object... values) {
        return hedao.pagedQuery(hql, pageNo, pageSize, values);
    }

    /**
     * @author Scott.wanglei
     * @since  2008-7-21
     * @param hql 查詢sql
     * @param start 分頁從哪一條數(shù)據(jù)開始
     * @param pageSize 每一個(gè)頁面的大小
     * @param values 查詢條件
     * @return page對象
     */
    public Page dataQuery(String hql, int start, int pageSize, Object... values) {
        return hedao.dataQuery(hql, start, pageSize, values);
    }

    /**
     * 分頁查詢函數(shù),使用已設(shè)好查詢條件與排序的<code>Criteria</code>.
     *
     * @param pageNo 頁號,從1開始.
     * @return 含總記錄數(shù)和當(dāng)前頁數(shù)據(jù)的Page對象.
     */
    public Page pagedQuery(Criteria criteria, int pageNo, int pageSize) {
        return hedao.pagedQuery(criteria, pageNo, pageSize);
    }
    
    /**
     * 分頁查詢函數(shù),根據(jù)entityClass和查詢條件參數(shù)創(chuàng)建默認(rèn)的<code>Criteria</code>.
     *
     * @param pageNo 頁號,從1開始.
     * @return 含總記錄數(shù)和當(dāng)前頁數(shù)據(jù)的Page對象.
     */
    @SuppressWarnings("unchecked")
    public Page pagedQuery(Class entityClass, int pageNo, int pageSize,
            Criterion... criterions) {
        return hedao.pagedQuery(entityClass, pageNo, pageSize, criterions);
    }

    @SuppressWarnings("unchecked")
    public Page pagedQuery(Class entityClass, int pageNo, int pageSize,
            String orderBy, boolean isAsc, Criterion... criterions) {
        return hedao.pagedQuery(entityClass, pageNo, pageSize, orderBy, isAsc, criterions);
    }

    /**
     * 判斷對象某些屬性的值在數(shù)據(jù)庫中是否唯一.
     *
     * @param uniquePropertyNames 在POJO里不能重復(fù)的屬性列表,以逗號分割 如"name,loginid,password"
     */
    public  boolean isUnique(Class<T> entityClass, Object entity,
            String uniquePropertyNames) {
        return hedao.isUnique(entity, uniquePropertyNames);
    }

    /**
     * 取得對象的主鍵值,輔助函數(shù).
     */
    @SuppressWarnings("unchecked")
    public Serializable getId(Class entityClass, Object entity)
            throws NoSuchMethodException, IllegalAccessException,
            InvocationTargetException {
        return hedao.getId(entityClass, entity);
    }

    /**
     * 取得對象的主鍵名,輔助函數(shù).
     */
    @SuppressWarnings("unchecked")
    public String getIdName(Class clazz) {
        return hedao.getIdName(clazz);
    }

}


使用時(shí)候的xml配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="    xmlns:xsi="    xsi:schemaLocation="http://www.springframework.org/schema/beans

    <bean id="hedao"
        class="com.demonstration.hibernate.dao.HibernateEntityDao" scope="prototype">
        <property name="sessionFactory">
            <ref bean="sessionFactory" />
        </property>
    </bean>

    <bean id="hexdao"
        class="com.demonstration.hibernate.dao.extend.HibernateEntityExtendDao" scope="prototype">
        <property name="sessionFactory">
            <ref bean="sessionFactory" />
        </property>
    </bean>


    <!--使用泛型DAO作為抽象基類-->
    <bean id="baseDao" class="com.demonstration.hibernate.basedao.BaseDao"
        abstract="true" depends-on="hedao,hexdao">
        <property name="hedao">
            <ref bean="hedao" />
        </property>
        <property name="hexdao">
            <ref bean="hexdao" />
        </property>
    </bean>
    
    <!--下面這個(gè)dao沒有寫任何java代碼完全有spring搞定 -->
    <!-- 配置實(shí)體類的DAO -->
    <bean id="demoDao" parent="baseDao">
        <constructor-arg>
                         <!--根據(jù)這個(gè)生成某一個(gè)實(shí)體的dao -->
            <value>com.demonstration.entityclass.Demodata</value>
        </constructor-arg>
    </bean>

</beans>

發(fā)表于 @ 2010年03月12日 14:08:00 | 評論( 2 ) | 編輯| 舉報(bào)| 收藏

 

本文來自CSDN博客,轉(zhuǎn)載請標(biāo)明出處:http://blog.csdn.net/jie8991/archive/2010/03/12/5373849.aspx

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
hibernate--basedao,借鑒別人的完善自己的
hibernate 的criteria 測試
Spring Framework之最佳實(shí)踐二
spring整合JPA總結(jié)
hibernate 通用泛型DAO
Hibernate3與spring的整合應(yīng)用-技術(shù)學(xué)習(xí)者
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服