一个好用的hibernate泛型dao

以前从springside2.0上搞下来的很好用的,基本实现dao零编码只要配置xml文件就行了。

先看图:


 
一共4层,com.demonstration.hibernate.basedao是我加的用来进一步解耦hibernate和spring的耦合。
原来的官方解释如下:
SpringSide对Hibernate做了三层封装:

第一层:HibernateGenericDao,基于spring的HibernateDaoSupport,但加入了分页函数与各种Finder函数,并使用泛型避免了返回值强制类型转换。

第二层:HibernateEntityDao,基于HibernateGenericDao,用泛型声明Dao所管理的Entity类,默认拥有该entity的CRUD方法。

第三层:HibernateExtendDao,基于HibernateEntityDao,主要扩展各种选择性的功能。

关于三个类的详细注解请看JavaDoc,大致描述如下:

1 HibernateGenericDao
   在Spring HibernateDaoSupport基础上封装的DAO,功能如下:

   1.应用泛型:使得find(), get() 这些函数不再返回Object,而是返回T,不再需要强制类型转换。

   2.提供各种finder的简便函数
      应用了JDK5可变参数的hsql查询函数:List find(String hql, Object... values),支持find(hql),find(hql, param1); find(hql,param1,param2);find(hql,new Object[] {param1,param2}) 四种接口。

      简单查询的简化函数:findBy(Class entityClass,String name,Object value) ,findUniqueBy(Class entityClass,String name, Object value),findByLike(Class entityClass,String name,Object value)

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

      Spring并没有很好的接口封装支持firstResult, maxResult, fetchsize,cache,cacheRegion 等多个查询参数,所以springside宁愿返回已设置好查询条件的Query和Criteria,让大家继续剩下的参数设置,最后再执行 list(),注意那几个参数可以连续设置的,如:

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

      Page是SpringSide自行封装的一个典型Page类,pagedQuery与hibernate自身分页查询的差别是先运行一次count,获得符合条件的总记录数。

      如果查询不需要总记录数,用普通的hibernate API,加上setFirstResult(),setMaxResult()就解决,不需要pagedQuery()。

   5.判别对象属性在数据库中唯一的函数:isUnique(Class<T> entityClass,Object entity,String names)。

2. HibernateEntityDao
    所有UserManager, ProductManager之类只管理一类对象的Manager类的基类,只需要在类定义处声明Entity类型即可

public class BookManager extends HibernateEntityDao<Book> {
}  通过<Book>的定义,避免了HibernateGenericDao类各方法中必有的Class entityClass参数。

  如果需要操作其他的Entity,比如BookManager可能需要处理Category(图书目录),可以注入CategoryManager。无需担心事务的问题,JavaEE的默认事务模型已能很好处理。

  如果没有对应的CategoryManager,或者各种原因不想注入的话,可以使用BookManager继承自 HibernateGenericDao的带entityClass参数的函数来操作Category的增删改,如Category category= this.get(Category.class, 1);

3. HibernateExtendDao
      此类演示SpringSide 所作的一些扩展,大家可以按照自己的需要进行修改和扩展。

     1. 支持对象不能被直接删除,只能设置状态列为无效。
        接口UndeleteableEntityOperation,定义了要支持此功能必须实现的函数。

        可以有接口(UndeletableEntity)和annotation(@Undeletable)两种形式来定义无效列,annotation列形式还可以定义标识对象已删除的状态属性的名称,用接口则必须实现setStatus()接口,在里面操作实际的状态属性。

第四层就是把HibernateEntityDao和HibernateExtendDao以属性注入的方式注入到basedao,IBasedao就全局接口程序中使用的就是它,这个接口的实现全调用HibernateEntityDao和HibernateExtendDao的方法。方便以后的更改和替换,这样IBasedao接口不变就不要修改业务层的代码了。

 


代码如下(从下到上):

Page.java

package com.demonstration.hibernate.dao.support;

import java.io.Serializable; 
import java.util.ArrayList; 
/** 
 * 分页对象. 包含当前页数据及分页信息如总记录数. 
 * 
 * @author springside 
 *  
 */ 
@SuppressWarnings("serial") 
public class Page implements Serializable {

    private static int DEFAULT_PAGE_SIZE = 20;

    private int pageSize = DEFAULT_PAGE_SIZE; // 每页的记录数

    private long start; // 当前页第一条数据在List中的位置,从0开始

    private Object data; // 当前页中存放的记录,类型一般为List

    private long totalCount; // 总记录数

    /** 
     * 构造方法,只构造空页. 
     */ 
    @SuppressWarnings("unchecked") 
    public Page() { 
        this(0, 0, DEFAULT_PAGE_SIZE, new ArrayList()); 
    }

    /** 
     * 默认构造方法. 
     * 
     * @param start  本页数据在数据库中的起始位置 
     * @param totalSize 数据库中总记录条数 
     * @param pageSize  本页容量 
     * @param data    本页包含的数据 
     */ 
    public Page(long start, long totalSize, int pageSize, Object data) { 
        this.pageSize = pageSize; 
        this.start = start; 
        this.totalCount = totalSize; 
        this.data = data; 
    }

    /** 
     * 取总记录数. 
     */ 
    public long getTotalCount() { 
        return this.totalCount; 
    }

    /** 
     * 取总页数. 
     */ 
    public long getTotalPageCount() { 
        if (totalCount % pageSize == 0) 
            return totalCount / pageSize; 
        else 
            return totalCount / pageSize + 1; 
    }

    /** 
     * 取每页数据容量. 
     */ 
    public int getPageSize() { 
        return pageSize; 
    }

    /** 
     * 取当前页中的记录. 
     */ 
    public Object getResult() { 
        return data; 
    }

    /** 
     * 取该页当前页码,页码从1开始. 
     */ 
    public long getCurrentPageNo() { 
        return start / pageSize + 1; 
    }

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

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

    /** 
     * 获取任一页第一条数据在数据集的位置,每页条数使用默认值. 
     * 
     * @see #getStartOfPage(int,int) 
     */ 
    protected static int getStartOfPage(int pageNo) { 
        return getStartOfPage(pageNo, DEFAULT_PAGE_SIZE); 
    }

    /** 
     * 获取任一页第一条数据在数据集的位置. 
     * 
     * @param pageNo   从1开始的页号 
     * @param pageSize 每页记录条数 
     * @return 该页第一条数据 
     */ 
    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时声明的父类的范型参数的类型. 如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时声明的父类的范型参数的类型. 如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;

/** 
 * 扩展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() { 
    }

    /** 
     * 循环向上转型,获取对象的DeclaredField. 
     * 
     * @throws NoSuchFieldException 如果没有该Field时抛出. 
     */ 
    public static Field getDeclaredField(Object object, String propertyName) throws NoSuchFieldException { 
        Assert.notNull(object); 
        Assert.hasText(propertyName); 
        return getDeclaredField(object.getClass(), propertyName); 
    }

    /** 
     * 循环向上转型,获取对象的DeclaredField. 
     * 
     * @throws NoSuchFieldException 如果没有该Field时抛出. 
     */ 
    @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不在当前类定义,继续向上转型 
            } 
        } 
        throw new NoSuchFieldException("No such field: " + clazz.getName() + '.' + propertyName); 
    }

    /** 
     * 暴力获取对象变量值,忽略private,protected修饰符的限制. 
     * 
     * @throws NoSuchFieldException 如果没有该Field时抛出. 
     */ 
    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; 
    }

    /** 
     * 暴力设置对象变量值,忽略private,protected修饰符的限制. 
     * 
     * @throws NoSuchFieldException 如果没有该Field时抛出. 
     */ 
    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); 
    }

    /** 
     * 暴力调用对象函数,忽略private,protected修饰符的限制. 
     * 
     * @throws NoSuchMethodException 如果没有该Method时抛出. 
     */ 
    @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) { 
                // 方法不在当前类定义,继续向上转型 
            } 
        }

        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函数名称. 
     */ 
    @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函数,如果找不到该方法,返回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用到的几个常量,因为要同时兼顾Interface与Annotation,所以集中放此. 
     */ 
    String UNVALID_VALUE = "-1";

    String NORMAL_VALUE = "0";

    String STATUS = "status";

    /** 
     * 取得所有状态为有效的对象. 
     */ 
    List<T> getAllValid();

    /** 
     * 删除对象,但如果是Undeleteable的entity,设置对象的状态而不是直接删除. 
     */ 
    void remove(Object entity);

    /** 
     * 获取过滤已删除对象的hql条件语句. 
     */ 
    String getUnDeletableHQL(); 
    /** 
     * 获取过滤已删除对象的Criterion条件语句. 
     */ 
    Criterion getUnDeletableCriterion(); 
}


IUndeletableEntity.java

package com.demonstration.hibernate.dao.extend;

/** 
 * 标识商业对象不能被删除,只能被设为无效的接口. 
 * 
 * @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;

/** 
 * 标识商业对象不能被删除,只能被设为无效的Annoation. 
 * <p/> 
 * 相比inferface的标示方式,annotation 方式更少侵入性,可以定义任意属性代表status,而默认为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;


/** 
 * 加强版的entity dao. 
 * <p>自动处理Undeletable Entity.<br> 
 * Undeletable Entity 在删除时只把状态设为无效,不会真正执行删除.<br> 
 * Undeletable Entity 可以通过annotation或接口两种形式来声明.<br> 
 * 其中annotation模式不限制状态列的属性名必须为"status",可以用注释来确定任意属性为状态属性.<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;

    /** 
     * 构造函数,初始化entity信息. 
     */ 
    public HibernateEntityExtendDao() { 
        entityInfo = new EntityInfo(entityClass); 
    }

    /** 
     * 取得所有状态为有效的对象. 
     * 
     * @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)); 
    }

    /** 
     * 重载保存函数,在保存前先调用onValid(T),进行书名不重复等数据库相关的校验. 
     * 
     * @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,设置对象的状态而不是直接删除. 
     * 
     * @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); 
    }

    /** 
     * 与数据库相关的校验,比如判断名字在数据库里有没有重复, 在保存时被调用,在子类重载. 
     * 
     * @see #save(Object) 
     */ 
    public void onValid(T entity) { 
    }

    /** 
     * 根据Map中的条件的Criteria查询. 
     * 
     * @param map Map中仅包含条件名与条件值,默认全部相同,可重载。 
     */ 
    public List<T> find(Map map) { 
        Criteria criteria = createCriteria(); 
        return find(criteria, map); 
    }

    /** 
     * 根据Map中的条件的Criteria查询. 
     * 
     * @param map Map中仅包含条件名与条件值,默认全部相同,可重载. 
     */ 
    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信息的内部类. 
 * 
 * @author springside 
 *  
 */ 
class EntityInfo { 
    boolean isUndeletable = false; // entity是否undeleteable的标志

    String statusProperty; // 标识状态的属性名

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

    /** 
     * 初始函数,判断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;

/** 
 * 针对单个Entity对象的操作定义.不依赖于具体ORM实现方案. 
 * 
 * @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>,提供分页函数和若干便捷查询方法,并对返回值作了泛型类型转换. 
 * 
 * @author springside 
 *  
 * @see HibernateDaoSupport 
 * @see HibernateEntityDao 
 */ 
@SuppressWarnings("unchecked") 
public class HibernateGenericDao extends HibernateDaoSupport { 
    /** 
     * 根据ID获取对象. 实际调用Hibernate的session.load()方法返回实体或其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); 
    }

    /** 
     * 获取全部对象,带排序字段与升降序参数. 
     */ 
    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); 
    }

    /** 
     * 根据ID删除对象. 
     */ 
    public <T> void removeById(Class<T> entityClass, Serializable id) { 
        remove(get(entityClass, id)); 
    }

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

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

    /** 
     * 创建Query对象. 对于需要first,max,fetchsize,cache,cacheRegion等诸多设置的函数,可以在返回Query后自行设置. 
     * 留意可以连续设置,如下: 
     * <pre> 
     * dao.getQuery(hql).setMaxResult(100).setCacheable(true).list(); 
     * </pre> 
     * 调用方式如下: 
     * <pre> 
     *        dao.createQuery(hql) 
     *        dao.createQuery(hql,arg0); 
     *        dao.createQuery(hql,arg0,arg1); 
     *        dao.createQuery(hql,new Object[arg0,arg1,arg2]) 
     * </pre> 
     * 
     * @param values 可变参数. 
     */ 
    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; 
    }

    /** 
     * 创建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; 
    }

    /** 
     * 创建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; 
    }

    /** 
     * 根据hql查询,直接使用HibernateTemplate的find函数. 
     * 
     * @param values 可变参数,见{@link #createQuery(String,Object...)} 
     */ 
    public List find(String hql, Object... values) { 
        Assert.hasText(hql); 
        return getHibernateTemplate().find(hql, values); 
    }

    /** 
     * 根据属性名和属性值查询对象. 
     * 
     * @return 符合条件的对象列表 
     */ 
    public <T> List<T> findBy(Class<T> entityClass, String propertyName, Object value) { 
        Assert.hasText(propertyName); 
        return createCriteria(entityClass, Restrictions.eq(propertyName, value)).list(); 
    }

    /** 
     * 根据属性名和属性值查询对象,带排序参数. 
     */ 
    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(); 
    }

    /** 
     * 根据属性名和属性值查询唯一对象. 
     * 
     * @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(); 
    }

    /** 
     * 分页查询函数,使用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(); 
        // 实际查询返回分页对象 
        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 分页从哪一条数据开始 
     * @param pageSize 每一个页面的大小 
     * @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(); 
        // 实际查询返回分页对象 
        int startIndex = start; 
        Query query = createQuery(hql, values); 
        List list = query.setFirstResult(startIndex).setMaxResults(pageSize).list();

        return new Page(startIndex, totalCount, pageSize, list); 
     } 
    /** 
     * 分页查询函数,使用已设好查询条件与排序的<code>Criteria</code>. 
     * 
     * @param pageNo 页号,从1开始. 
     * @return 含总记录数和当前页数据的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条件取出来,清空两者来执行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 "); 
        }

        // 执行查询 
        int totalCount = (Integer) criteria.setProjection(Projections.rowCount()).uniqueResult();

        // 将之前的Projection和OrderBy条件重新设回去 
        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); 
    }

    /** 
     * 分页查询函数,根据entityClass和查询条件参数创建默认的<code>Criteria</code>. 
     * 
     * @param pageNo 页号,从1开始. 
     * @return 含总记录数和当前页数据的Page对象. 
     */ 
    public Page pagedQuery(Class entityClass, int pageNo, int pageSize, Criterion... criterions) { 
        Criteria criteria = createCriteria(entityClass, criterions); 
        return pagedQuery(criteria, pageNo, pageSize); 
    }

    /** 
     * 分页查询函数,根据entityClass和查询条件参数,排序参数创建默认的<code>Criteria</code>. 
     * 
     * @param pageNo 页号,从1开始. 
     * @return 含总记录数和当前页数据的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); 
    }

    /** 
     * 判断对象某些属性的值在数据库中是否唯一. 
     * 
     * @param uniquePropertyNames 在POJO里不能重复的属性列表,以逗号分割 如"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 { 
            // 循环加入唯一列 
            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; 
    }

    /** 
     * 取得对象的主键值,辅助函数. 
     */ 
    public Serializable getId(Class entityClass, Object entity) throws NoSuchMethodException, IllegalAccessException, 
            InvocationTargetException { 
        Assert.notNull(entity); 
        Assert.notNull(entityClass); 
        return (Serializable) PropertyUtils.getProperty(entity, getIdName(entityClass)); 
    }

    /** 
     * 取得对象的主键名,辅助函数. 
     */ 
    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;

/** 
 * 负责为单个Entity对象提供CRUD操作的Hibernate DAO基类. <p/> 子类只要在类定义时指定所管理Entity的Class, 
 * 即拥有对单个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类型.

    /** 
     * 在构造函数中将泛型T.class赋给entityClass. 
     */ 
    public HibernateEntityDao() { 
        entityClass = GenericsUtils.getSuperClassGenricType(getClass()); 
    }

    /** 
     * 重载构造函数 让spring提供构造函数注入 
     */ 
    public HibernateEntityDao(Class<T> type) { 
        this.entityClass = type; 
    } 
     
    /** 
     * 取得entityClass.JDK1.4不支持泛型的子类可以抛开Class<T> entityClass,重载此函数达到相同效果。 
     */ 
    protected Class<T> getEntityClass() { 
        return entityClass; 
    } 
     
    public void setEntityClass(Class<T> type){ 
        this.entityClass=type; 
    }

    /** 
     * 根据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()); 
    }

    /** 
     * 获取全部对象,带排序参数. 
     *  
     * @see HibernateGenericDao#getAll(Class,String,boolean) 
     */ 
    public List<T> getAll(String orderBy, boolean isAsc) { 
        return getAll(getEntityClass(), orderBy, isAsc); 
    }

    /** 
     * 根据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,带排序参数. 
     *  
     * @see HibernateGenericDao#createCriteria(Class,String,boolean,Criterion[]) 
     */ 
    public Criteria createCriteria(String orderBy, boolean isAsc, 
            Criterion... criterions) { 
        return createCriteria(getEntityClass(), orderBy, isAsc, criterions); 
    }

    /** 
     * 根据属性名和属性值查询对象. 
     *  
     * @return 符合条件的对象列表 
     * @see HibernateGenericDao#findBy(Class,String,Object) 
     */ 
    public List<T> findBy(String propertyName, Object value) { 
        return findBy(getEntityClass(), propertyName, value); 
    }

    /** 
     * 根据属性名和属性值查询对象,带排序参数. 
     *  
     * @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); 
    }

    /** 
     * 根据属性名和属性值查询单个对象. 
     *  
     * @return 符合条件的唯一对象 or null 
     * @see HibernateGenericDao#findUniqueBy(Class,String,Object) 
     */ 
    public T findUniqueBy(String propertyName, Object value) { 
        return findUniqueBy(getEntityClass(), propertyName, value); 
    }

    /** 
     * 判断对象某些属性的值在数据库中唯一. 
     *  
     * @param uniquePropertyNames 
     *            在POJO里不能重复的属性列表,以逗号分割 如"name,loginid,password" 
     * @see HibernateGenericDao#isUnique(Class,Object,String) 
     */ 
    public boolean isUnique(Object entity, String uniquePropertyNames) { 
        return isUnique(getEntityClass(), entity, uniquePropertyNames); 
    }

    /** 
     * 消除与 Hibernate Session 的关联 
     *  
     * @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的所有操作, 
 * 实现类由spring注入HibernateEntityDao和HibernateEntityExtendDao来实现 
 * 最大限度的解耦hibernate持久层的操作 
 */ 
public interface IBaseDao<T> {

    /** 
     * 根据ID获取对象. 
     *  
     * @see HibernateGenericDao#getId(Class,Object) 
     */ 
    public T get(Serializable id); 
     
    /** 
     * 获取全部对象 
     *  
     * @see HibernateGenericDao#getAll(Class) 
     */ 
    public List<T> getAll(); 
     
    /** 
     * 获取全部对象,带排序参数. 
     *  
     * @see HibernateGenericDao#getAll(Class,String,boolean) 
     */ 
    public List<T> getAll(String orderBy, boolean isAsc); 
     
    /** 
     * 根据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,带排序参数. 
     *  
     * @see HibernateGenericDao#createCriteria(Class,String,boolean,Criterion[]) 
     */ 
    public Criteria createCriteria(String orderBy, boolean isAsc, 
            Criterion... criterions); 
     
    /** 
     * 根据属性名和属性值查询对象. 
     *  
     * @return 符合条件的对象列表 
     * @see HibernateGenericDao#findBy(Class,String,Object) 
     */ 
    public List<T> findBy(String propertyName, Object value); 
     
    /** 
     * 根据属性名和属性值查询对象,带排序参数. 
     *  
     * @return 符合条件的对象列表 
     * @see HibernateGenericDao#findBy(Class,String,Object,String,boolean) 
     */ 
    public List<T> findBy(String propertyName, Object value, String orderBy, 
            boolean isAsc); 
     
    /** 
     * 根据属性名和属性值查询单个对象. 
     *  
     * @return 符合条件的唯一对象 or null 
     * @see HibernateGenericDao#findUniqueBy(Class,String,Object) 
     */ 
    public T findUniqueBy(String propertyName, Object value); 
     
    /** 
     * 判断对象某些属性的值在数据库中唯一. 
     *  
     * @param uniquePropertyNames 
     *            在POJO里不能重复的属性列表,以逗号分割 如"name,loginid,password" 
     * @see HibernateGenericDao#isUnique(Class,Object,String) 
     */ 
    public boolean isUnique(Object entity, String uniquePropertyNames); 
     
    /** 
     * 消除与 Hibernate Session 的关联 
     *  
     * @param entity 
     */ 
    public void evit(Object entity); 
     
    /*******************************************************************************************/ 
     
    /** 
     * 取得所有状态为有效的对象. 
     * 
     * @see IUndeleteableEntityOperation#getAllValid() 
     */ 
    public List<T> getAllValid(); 
     
    /** 
     * 获取过滤已删除对象的hql条件语句. 
     * 
     * @see IUndeleteableEntityOperation#getUnDeletableHQL() 
     */ 
    public String getUnDeletableHQL(); 
     
    /** 
     * 获取过滤已删除对象的Criterion条件语句. 
     * 
     * @see UndeleteableEntityOperation# 
     */ 
    public Criterion getUnDeletableCriterion(); 
     
    /** 
     * 重载保存函数,在保存前先调用onValid(T),进行书名不重复等数据库相关的校验. 
     * 
     * @see #onValid(Object) 
     * @see HibernateEntityDao#save(Object) 
     */ 
    public void saveOnValid(Object entity); 
     
    /** 
     * 删除对象,如果是Undeleteable的entity,设置对象的状态而不是直接删除. 
     * 
     * @see HibernateEntityDao#remove(Object) 
     */ 
    public void removeUndeleteable(Object entity); 
     
    /** 
     * 与数据库相关的校验,比如判断名字在数据库里有没有重复, 在保存时被调用,在子类重载. 
     * 
     * @see #save(Object) 
     */ 
    public void onValid(T entity); 
     
    /** 
     * 根据Map中的条件的Criteria查询. 
     * 
     * @param map Map中仅包含条件名与条件值,默认全部相同,可重载。 
     */ 
    @SuppressWarnings("unchecked") 
    public List<T> find(Map map); 
     
    /** 
     * 根据Map中的条件的Criteria查询. 
     * 
     * @param map Map中仅包含条件名与条件值,默认全部相同,可重载. 
     */ 
    @SuppressWarnings("unchecked") 
    public List<T> find(Criteria criteria, Map map); 
     
    /*******************************************************************************************/ 
     
    /** 
     * 根据ID获取对象. 实际调用Hibernate的session.load()方法返回实体或其proxy对象. 如果对象不存在,抛出异常. 
     */ 
    public T get(Class<T> entityClass, Serializable id); 
     
    /** 
     * 获取全部对象. 
     */ 
    public  List<T> getAll(Class<T> entityClass); 
     
    /** 
     * 获取全部对象,带排序字段与升降序参数. 
     */ 
    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(); 
     
    /** 
     * 创建Query对象. 对于需要first,max,fetchsize,cache,cacheRegion等诸多设置的函数,可以在返回Query后自行设置. 
     * 留意可以连续设置,如下: 
     * <pre> 
     * dao.getQuery(hql).setMaxResult(100).setCacheable(true).list(); 
     * </pre> 
     * 调用方式如下: 
     * <pre> 
     *        dao.createQuery(hql) 
     *        dao.createQuery(hql,arg0); 
     *        dao.createQuery(hql,arg0,arg1); 
     *        dao.createQuery(hql,new Object[arg0,arg1,arg2]) 
     * </pre> 
     * 
     * @param values 可变参数. 
     */ 
    public Query createQuery(String hql, Object... values); 
     
    /** 
     * 创建Criteria对象. 
     * 
     * @param criterions 可变的Restrictions条件列表,见{@link #createQuery(String,Object...)} 
     */ 
    public  Criteria createCriteria(Class<T> entityClass, Criterion... criterions); 
     
    /** 
     * 创建Criteria对象,带排序字段与升降序字段. 
     * 
     * @see #createCriteria(Class,Criterion[]) 
     */ 
    public  Criteria createCriteria(Class<T> entityClass, String orderBy, boolean isAsc, Criterion... criterions); 
     
    /** 
     * 根据hql查询,直接使用HibernateTemplate的find函数. 
     * 
     * @param values 可变参数,见{@link #createQuery(String,Object...)} 
     */ 
    @SuppressWarnings("unchecked") 
    public List find(String hql, Object... values); 
     
    /** 
     * 根据属性名和属性值查询对象. 
     * 
     * @return 符合条件的对象列表 
     */ 
    public  List<T> findBy(Class<T> entityClass, String propertyName, Object value); 
     
    /** 
     * 根据属性名和属性值查询对象,带排序参数. 
     */ 
    public  List<T> findBy(Class<T> entityClass, String propertyName, Object value, String orderBy, boolean isAsc); 
     
    /** 
     * 根据属性名和属性值查询唯一对象. 
     * 
     * @return 符合条件的唯一对象 or null if not found. 
     */ 
    public  T findUniqueBy(Class<T> entityClass, String propertyName, Object value); 
     
    /** 
     * 分页查询函数,使用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 分页从哪一条数据开始 
     * @param pageSize 每一个页面的大小 
     * @param values 查询条件 
     * @return page对象 
     */ 
    public Page dataQuery(String hql, int start, int pageSize, Object... values); 
     
    /** 
     * 分页查询函数,使用已设好查询条件与排序的<code>Criteria</code>. 
     * 
     * @param pageNo 页号,从1开始. 
     * @return 含总记录数和当前页数据的Page对象. 
     */ 
    public Page pagedQuery(Criteria criteria, int pageNo, int pageSize); 
     
    /** 
     * 分页查询函数,根据entityClass和查询条件参数创建默认的<code>Criteria</code>. 
     * 
     * @param pageNo 页号,从1开始. 
     * @return 含总记录数和当前页数据的Page对象. 
     */ 
    @SuppressWarnings("unchecked") 
    public Page pagedQuery(Class entityClass, int pageNo, int pageSize, Criterion... criterions); 
     
    /** 
     * 分页查询函数,根据entityClass和查询条件参数,排序参数创建默认的<code>Criteria</code>. 
     * 
     * @param pageNo 页号,从1开始. 
     * @return 含总记录数和当前页数据的Page对象. 
     */ 
    @SuppressWarnings("unchecked") 
    public Page pagedQuery(Class entityClass, int pageNo, int pageSize, String orderBy, boolean isAsc, 
               Criterion... criterions); 
     
    /** 
     * 判断对象某些属性的值在数据库中是否唯一. 
     * 
     * @param uniquePropertyNames 在POJO里不能重复的属性列表,以逗号分割 如"name,loginid,password" 
     */ 
    public  boolean isUnique(Class<T> entityClass, Object entity, String uniquePropertyNames); 
     
    /** 
     * 取得对象的主键值,辅助函数. 
     */ 
    @SuppressWarnings("unchecked") 
    public Serializable getId(Class entityClass, Object entity) throws NoSuchMethodException, IllegalAccessException, 
    InvocationTargetException ; 
     
    /** 
     * 取得对象的主键名,辅助函数. 
     */ 
    @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的实现类通过spring注入HibernateEntityDao和HibernateEntityExtendDao来实现 
 */ 
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提供构造函数注入 
     */ 
    public BaseDao(Class<T> type) { 
        this.entityClass = type; 
    } 
     
    public BaseDao(){} 
    /** 
     * 根据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(); 
    }


    /** 
     * 获取全部对象,带排序参数. 
     *  
     * @see HibernateGenericDao#getAll(Class,String,boolean) 
     */ 
    public List<T> getAll(String orderBy, boolean isAsc) { 
        return hedao.getAll(orderBy, isAsc); 
    }

    /** 
     * 根据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,带排序参数. 
     *  
     * @see HibernateGenericDao#createCriteria(Class,String,boolean,Criterion[]) 
     */ 
    public Criteria createCriteria(String orderBy, boolean isAsc, 
            Criterion... criterions) { 
        return hedao.createCriteria(orderBy, isAsc, criterions); 
    }

    /** 
     * 根据属性名和属性值查询对象. 
     *  
     * @return 符合条件的对象列表 
     * @see HibernateGenericDao#findBy(Class,String,Object) 
     */ 
    public List<T> findBy(String propertyName, Object value) { 
        return hedao.findBy(propertyName, value); 
    }

    /** 
     * 根据属性名和属性值查询对象,带排序参数. 
     *  
     * @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); 
    }

    /** 
     * 根据属性名和属性值查询单个对象. 
     *  
     * @return 符合条件的唯一对象 or null 
     * @see HibernateGenericDao#findUniqueBy(Class,String,Object) 
     */ 
    public T findUniqueBy(String propertyName, Object value) { 
        return hedao.findUniqueBy(propertyName, value); 
    }

    /** 
     * 判断对象某些属性的值在数据库中唯一. 
     *  
     * @param uniquePropertyNames 
     *            在POJO里不能重复的属性列表,以逗号分割 如"name,loginid,password" 
     * @see HibernateGenericDao#isUnique(Class,Object,String) 
     */ 
    public boolean isUnique(Object entity, String uniquePropertyNames) { 
        return hedao.isUnique(entity, uniquePropertyNames); 
    }

    /** 
     * 消除与 Hibernate Session 的关联 
     *  
     * @param entity 
     */ 
    public void evit(Object entity) { 
        hedao.evit(entity); 
    }

    /** 
     * 取得所有状态为有效的对象. 
     * 
     * @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(); 
    }

    /** 
     * 重载保存函数,在保存前先调用onValid(T),进行书名不重复等数据库相关的校验. 
     * 
     * @see #onValid(Object) 
     * @see HibernateEntityDao#save(Object) 
     */ 
    public void saveOnValid(Object entity) { 
         hexdao.save(entity); 
    }

    /** 
     * 删除对象,如果是Undeleteable的entity,设置对象的状态而不是直接删除. 
     * 
     * @see HibernateEntityDao#remove(Object) 
     */ 
    public void removeUndeleteable(Object entity) { 
           hexdao.remove(entity); 
    }

    /** 
     * 与数据库相关的校验,比如判断名字在数据库里有没有重复, 在保存时被调用,在此可重写. 
     * 
     * @see #save(Object) 
     */ 
    public void onValid(T entity) { 
            
    }

    /** 
     * 根据Map中的条件的Criteria查询. 
     * 
     * @param map Map中仅包含条件名与条件值,默认全部相同,可重载。 
     */ 
    @SuppressWarnings("unchecked") 
    public List<T> find(Map map) { 
        return hexdao.find(map); 
    }

    /** 
     * 根据Map中的条件的Criteria查询. 
     * 
     * @param map Map中仅包含条件名与条件值,默认全部相同,可重载. 
     */ 
    @SuppressWarnings("unchecked") 
    public List<T> find(Criteria criteria, Map map) { 
        return hexdao.find(criteria, map); 
    }

    /** 
     * 根据ID获取对象. 实际调用Hibernate的session.load()方法返回实体或其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); 
    }

    /** 
     * 获取全部对象,带排序字段与升降序参数. 
     */ 
    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(); 
    }

    /** 
     * 创建Query对象. 对于需要first,max,fetchsize,cache,cacheRegion等诸多设置的函数,可以在返回Query后自行设置. 
     * 留意可以连续设置,如下: 
     * <pre> 
     * dao.getQuery(hql).setMaxResult(100).setCacheable(true).list(); 
     * </pre> 
     * 调用方式如下: 
     * <pre> 
     *        dao.createQuery(hql) 
     *        dao.createQuery(hql,arg0); 
     *        dao.createQuery(hql,arg0,arg1); 
     *        dao.createQuery(hql,new Object[arg0,arg1,arg2]) 
     * </pre> 
     * 
     * @param values 可变参数. 
     */ 
    public Query createQuery(String hql, Object... values) { 
         
        return hedao.createQuery(hql, values); 
    }

    /** 
     * 创建Criteria对象. 
     * 
     * @param criterions 可变的Restrictions条件列表,见{@link #createQuery(String,Object...)} 
     */ 
    public Criteria createCriteria(Class<T> entityClass, 
            Criterion... criterions) { 
         
        return hedao.createCriteria(entityClass, criterions); 
    }

    /** 
     * 创建Criteria对象,带排序字段与升降序字段. 
     * 
     * @see #createCriteria(Class,Criterion[]) 
     */ 
    public Criteria createCriteria(Class<T> entityClass, String orderBy, 
            boolean isAsc, Criterion... criterions) { 
        return hedao.createCriteria(entityClass, orderBy, isAsc, criterions); 
    }

    /** 
     * 根据hql查询,直接使用HibernateTemplate的find函数. 
     * 
     * @param values 可变参数,见{@link #createQuery(String,Object...)} 
     */ 
    @SuppressWarnings("unchecked") 
    public List find(String hql, Object... values) { 
        return hedao.find(hql, values); 
    }

    /** 
     * 根据属性名和属性值查询对象. 
     * 
     * @return 符合条件的对象列表 
     */ 
    public  List<T> findBy(Class<T> entityClass, String propertyName, 
            Object value) { 
         
        return hedao.findBy(entityClass, propertyName, value); 
    }

    /** 
     * 根据属性名和属性值查询对象,带排序参数. 
     */ 
    public List<T> findBy(Class<T> entityClass, String propertyName, 
            Object value, String orderBy, boolean isAsc) { 
        return hedao.findBy(entityClass, propertyName, value, orderBy, isAsc); 
    }

    /** 
     * 根据属性名和属性值查询唯一对象. 
     * 
     * @return 符合条件的唯一对象 or null if not found. 
     */ 
    public T findUniqueBy(Class<T> entityClass, String propertyName, 
            Object value) { 
        return hedao.findUniqueBy(propertyName, value); 
    }

    /** 
     * 分页查询函数,使用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 分页从哪一条数据开始 
     * @param pageSize 每一个页面的大小 
     * @param values 查询条件 
     * @return page对象 
     */ 
    public Page dataQuery(String hql, int start, int pageSize, Object... values) { 
        return hedao.dataQuery(hql, start, pageSize, values); 
    }

    /** 
     * 分页查询函数,使用已设好查询条件与排序的<code>Criteria</code>. 
     * 
     * @param pageNo 页号,从1开始. 
     * @return 含总记录数和当前页数据的Page对象. 
     */ 
    public Page pagedQuery(Criteria criteria, int pageNo, int pageSize) { 
        return hedao.pagedQuery(criteria, pageNo, pageSize); 
    } 
     
    /** 
     * 分页查询函数,根据entityClass和查询条件参数创建默认的<code>Criteria</code>. 
     * 
     * @param pageNo 页号,从1开始. 
     * @return 含总记录数和当前页数据的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); 
    }

    /** 
     * 判断对象某些属性的值在数据库中是否唯一. 
     * 
     * @param uniquePropertyNames 在POJO里不能重复的属性列表,以逗号分割 如"name,loginid,password" 
     */ 
    public  boolean isUnique(Class<T> entityClass, Object entity, 
            String uniquePropertyNames) { 
        return hedao.isUnique(entity, uniquePropertyNames); 
    }

    /** 
     * 取得对象的主键值,辅助函数. 
     */ 
    @SuppressWarnings("unchecked") 
    public Serializable getId(Class entityClass, Object entity) 
            throws NoSuchMethodException, IllegalAccessException, 
            InvocationTargetException { 
        return hedao.getId(entityClass, entity); 
    }

    /** 
     * 取得对象的主键名,辅助函数. 
     */ 
    @SuppressWarnings("unchecked") 
    public String getIdName(Class clazz) { 
        return hedao.getIdName(clazz); 
    }

}


使用时候的xml配置:
<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance
    xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd">

    <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> 
     
    <!--下面这个dao没有写任何java代码完全有spring搞定 --> 
    <!-- 配置实体类的DAO --> 
    <bean id="demoDao" parent="baseDao"> 
        <constructor-arg> 
                         <!--根据这个生成某一个实体的dao --> 
            <value>com.demonstration.entityclass.Demodata</value> 
        </constructor-arg> 
    </bean>

</beans>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值