一个好用的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/beans http://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>

展开阅读全文

高分急救,一个异常问题,HIBERNATE和SPRING结合,泛型DAO的问题

01-28

我自己写了一个泛型DAO,用的是SPRING的HibernateDaoSupport来获得hibernateTemplate。rn异常如下:rn严重: Servlet.service() for servlet fms threw exceptionrnjava.lang.NullPointerExceptionrn at core.service.impl.GenericManagerImpl.getAll(GenericManagerImpl.java:58)rn at fms.web.CommonController.commonHandler(CommonController.java:29)rn at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)rn at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)rn at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)rn at java.lang.reflect.Method.invoke(Unknown Source)rn at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.doInvokeMethod(HandlerMethodInvoker.java:421)rn at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:136)rn at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:326)rn at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:313)rn at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:875)rn at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:807)rn at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571)rn at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:501)rn at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)rn at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)rn at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)rn at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)rn at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)rn at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)rn at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)rn at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)rn at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)rn at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)rn at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)rn at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)rn at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)rn at java.lang.Thread.run(Unknown Source)rnrnrn我第一次写泛型DAO接口和实现类如下:如果大哥们现成的泛型DAO提供给我参考最好,能加我QQ吧532054105.十分感谢了!!!rn/**rn * rn */rnpackage core.dao;rnrnimport java.io.Serializable;rnimport java.util.List;rnrn/**rn * 公用的核心DAO接口,提供常用CRUD操作rn * @author dengjiern *rn */rnpublic interface GenericDao rnrn /**rn * 根据ID值进行查询rn * @param id 记录ID值rn */rn public T get(ID id);rn /**rn * 查询全部记录rn */rn public List getAll();rn /**rn * 保存实体类rn * @param entity 实体类rn */rn public void save(T entity);rn /**rn * 更新实例类rn * @param entityrn */rn public void update(T entity);rn /**rn * 删除操作,删除一个实体类rn * @param entity 要删除的实体类rn */rn public void delete(T entity);rn /**rn * 根据字段值条件进行查询rn * @param property 字段名称rn * @param value 字段条件值rn */rn public List findByProperty(String property,Object value);rnrnrnrn实现类:rn/**rn * rn */rnpackage core.dao.impl;rnrnimport java.io.Serializable;rnimport java.lang.reflect.ParameterizedType;rnimport java.util.List;rnrnimport org.hibernate.criterion.DetachedCriteria;rnimport org.hibernate.criterion.Restrictions;rnimport org.springframework.orm.hibernate3.support.HibernateDaoSupport;rnrnimport core.dao.GenericDao;rnrn/**rn * 公用基本DAO的实现类rn * @author dengjiern * rn */rnpublic class GenericDaoImpl extends HibernateDaoSupport implements GenericDao rn /**rn * 调用反射方法得到不同的实体类rn * @returnrn */rn @SuppressWarnings("unchecked") rn private Class type()rn return (Class) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; rn rnrn /**rn * 删除操作,删除一个实体类rn * @param entity 要删除的实体类rn */rn public void delete(T entity) rn this.getHibernateTemplate().delete(entity); rn rnrn /**rn * 根据字段值条件进行查询rn * @param property 字段名称rn * @param value 字段条件值rn */rn @SuppressWarnings("unchecked") rn public List findByProperty(String property, Object value) rn return this.getHibernateTemplate().findByCriteria( rn DetachedCriteria.forClass(type()).add(Restrictions.eq(property, value))); rn rn /**rn * 根据ID值进行查询rn * @param id 记录ID值rn */rn @SuppressWarnings("unchecked") rn public Object get(Serializable id) rn return this.getHibernateTemplate().get(type(), id);rn rn /**rn * 查询全部记录rn */rn @SuppressWarnings("unchecked") rn public List getAll() rn return this.getHibernateTemplate().loadAll(type());rn rn /**rn * 保存实体类rn * @param entity 实体类rn */rn public void save(T entity) rn this.getHibernateTemplate().save(entity); rn rn /**rn * 更新实例类rn * @param entityrn */rn public void update(T entity) rn this.getHibernateTemplate().update(entity); rn rnrnrnservice层的接口:rn/**rn * rn */rnpackage core.service;rnrnimport java.io.Serializable;rnimport java.util.List;rnrn/**rn * service层的核心manger接口rn * @author dengjiern *rn */rnpublic interface GenericManager rn /**rn * 根据ID值进行查询rn * @param id 记录ID值rn */rn public T get(ID id);rn /**rn * 查询全部记录rn */rn public List getAll();rn /**rn * 保存实体类rn * @param entity 实体类rn */rn public void save(T entity);rn /**rn * 更新实例类rn * @param entityrn */rn public void update(T entity);rn /**rn * 删除操作,删除一个实体类rn * @param entity 要删除的实体类rn */rn public void delete(T entity);rn /**rn * 根据字段值条件进行查询rn * @param property 字段名称rn * @param value 字段条件值rn */rn public List findByProperty(String property,Object value);rnrnrn实现类:rn/**rn * rn */rnpackage core.service.impl;rnrnimport java.io.Serializable;rnimport java.util.List;rnrnimport core.dao.GenericDao;rnimport core.service.GenericManager;rnrn/**rn * service层的公用服务类,提供基本DAO的CRUD操作rn * @author dengjiern *rn */rn@SuppressWarnings("unchecked")rnpublic class GenericManagerImpl implements GenericManager rn private GenericDao genericDao;rn rn public GenericDao getGenericDao() rn return genericDao;rn rnrn public void setGenericDao(GenericDao genericDao) rn this.genericDao = genericDao;rn rn public void delete(Object entity) rn genericDao.delete(entity);rn rn rn public List findByProperty(String property, Object value) rn return genericDao.findByProperty(property, value);rn rn public Object get(Serializable id) rn return genericDao.get(id);rn rn public List getAll() rn return genericDao.getAll();rn rn public void save(Object entity) rn genericDao.save(entity); rn rn public void update(Object entity) rn genericDao.update(entity); rn rnrn如果那个大哥能提供现成的泛型DAO给我参考下最好。谢谢了。十分感谢了。希望DAO接口和实现都有。要采用SPRING的支持。 论坛

Hibernat泛型DAO问题

04-27

在程序中使用springside的DAO,使用级联时候出现问题rnrn[code="java"]rnrnpublic class SimpleHibernateDao rnrn protected Logger logger = LoggerFactory.getLogger(getClass());rnrn protected SessionFactory sessionFactory;rnrn protected Class entityClass;rnrn /**rn * 用于扩展的DAO子类使用的构造函数.rn * rn * 通过子类的泛型定义取得对象类型Class.rn * eg.rn * public class UserDao extends SimpleHibernateDaorn */rn public SimpleHibernateDao() rn this.entityClass = ReflectionUtils.getSuperClassGenricType(getClass());rn rnrn /**rn * 用于Service层直接使用SimpleHibernateDAO的构造函数.rn * eg.rn * SimpleHibernateDao userDao = new SimpleHibernateDao(sessionFactory, User.class);rn */rn public SimpleHibernateDao(final SessionFactory sessionFactory, final Class entityClass) rn this.sessionFactory = sessionFactory;rn this.entityClass = entityClass;rn rnrn public SessionFactory getSessionFactory() rn return sessionFactory;rn rnrn///................其他省略rnrnrnrnrn[code="java"]rnpublic class HibernateDao extends SimpleHibernateDao rn /**rn * 用于扩展的DAO子类使用的构造函数.rn * rn * 通过子类的泛型定义取得对象类型Class.rn * eg.rn * public class UserDao extends HibernateDaorn * rn */rn public HibernateDao() rn super();rn rnrn /**rn * 用于Service层直接使用HibernateDAO的构造函数.rn * eg.rn * HibernateDao userDao = new HibernateDao(sessionFactory, User.class);rn */rn public HibernateDao(final SessionFactory sessionFactory, final Class entityClass) rn super(sessionFactory, entityClass);rn rnrn // 分页查询函数 //rnrn /**rn * 分页获取全部对象. rn */rn public Page getAll(final Page page) rn return findByCriteria(page);rn rn//其他rnrnrn下面是实体rn[/code]rnrn[code="java"]rnrn@Entityrn@Table(name = "WFPROCESSINST", schema = "TSSA")rn@Proxy(lazy=false)rnpublic class Wfprocessinst implements java.io.Serializable rnprivate BigDecimal processinstid;rn@Idrn @Column(name = "PROCESSINSTID", unique = true, nullable = false, precision = 22, scale = 0)rn public BigDecimal getProcessinstid() rn return this.processinstid;rn rnrn public void setProcessinstid(BigDecimal processinstid) rn this.processinstid = processinstid;rn rn private String processinstname;rn private Set wftransitions = new HashSet(0);rn @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "wfprocessinst")rn public Set getWfactivityinsts() rn return this.wfactivityinsts;rn rnrn public void setWfactivityinsts(Set wfactivityinsts) rn this.wfactivityinsts = wfactivityinsts;rn rnrnrn[/code]rnrnrn当fetch = FetchType.EAGER 报错,为FetchType.LAZY 正常。rnrnrn异常rnrnrn[WARN ]2009-04-27 16:26:57,868 org.hibernate.util.JDBCExceptionReporter SQL Error: 17027, SQLState: nullrn[ERROR]2009-04-27 16:26:57,868 org.hibernate.util.JDBCExceptionReporter 流已被关闭rn[INFO ]2009-04-27 16:26:57,870 org.hibernate.event.def.DefaultLoadEventListener Error performing load commandrnorg.hibernate.exception.GenericJDBCException: could not load an entity: [cn.com.starit.orm.hibernate.dojo.Wfprocessinst#8809358]rn at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:103)rn at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:91)rn at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)rn at org.hibernate.loader.Loader.loadEntity(Loader.java:1874)rn at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:48)rn at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:42)rn at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3044)rn at org.hibernate.event.def.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:395)rn at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:375)rn at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:139)rn at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:179)rn at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:103)rn at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:878)rn at org.hibernate.impl.SessionImpl.load(SessionImpl.java:795)rn at org.hibernate.impl.SessionImpl.load(SessionImpl.java:788)rn at cn.com.starit.orm.hibernate.SimpleHibernateDao.get(SimpleHibernateDao.java:114)rn at cn.com.starit.orm.hibernate.EntityManager.get(EntityManager.java:38)rn at cn.com.starit.orm.hibernate.EntityManager$$FastClassByCGLIB$$7a912d89.invoke()rn at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:149)rn at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:700)rn at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)rn at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)rn at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)rn at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:635)rn at cn.com.starit.service.WFManager$$EnhancerByCGLIB$$e9c4798f.get()rn at cn.com.starit.action.UserAction.main(UserAction.java:21)rnCaused by: java.sql.SQLException: 流已被关闭rn at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112)rn at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:146)rn at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:208)rn at oracle.jdbc.driver.LongAccessor.getBytes(LongAccessor.java:151)rn at oracle.jdbc.driver.LongAccessor.getString(LongAccessor.java:193)rn at oracle.jdbc.driver.T4CLongAccessor.getString(T4CLongAccessor.java:422)rn at oracle.jdbc.driver.OracleResultSetImpl.getString(OracleResultSetImpl.java:397)rn at oracle.jdbc.driver.OracleResultSet.getString(OracleResultSet.java:1515)rn at org.hibernate.type.StringType.get(StringType.java:18)rn at org.hibernate.type.NullableType.nullSafeGet(NullableType.java:163)rn at org.hibernate.type.NullableType.nullSafeGet(NullableType.java:154)rn at org.hibernate.type.AbstractType.hydrate(AbstractType.java:81)rn at org.hibernate.persister.entity.AbstractEntityPersister.hydrate(AbstractEntityPersister.java:2096)rn at org.hibernate.loader.Loader.loadFromResultSet(Loader.java:1380)rn at org.hibernate.loader.Loader.instanceNotYetLoaded(Loader.java:1308)rn at org.hibernate.loader.Loader.getRow(Loader.java:1206)rn at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:580)rn at org.hibernate.loader.Loader.doQuery(Loader.java:701)rn at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:236)rn at org.hibernate.loader.Loader.loadEntity(Loader.java:1860)n[b]问题补充:[/b]n代码被我没有有发完,是有的。n[b]问题补充:[/b]n级联查询rnApplicationContext context = new ClassPathXmlApplicationContext(rn "classpath:config/ApplicationContext.xml");rn WFManager wf = (WFManager) context.getBean("WFManager");rn Wfprocessinst dd;rn try rn dd= wf.get(new BigDecimal(8809358));rn System.out.println(dd.getProcessinstname());rn //Iterator ac= dd.getWfactivityinsts().iterator();rn// while(ac.hasNext())rn// System.out.println(ac.next().getActivityinstname());rn// rn// rn catch (Exception e) rn e.printStackTrace();rn rn System.out.println("this is a test");rn注释那一部分有问题n[b]问题补充:[/b]n我做了一个简单例子,还是错的,控制台输出的SQL是正确的n[b]问题补充:[/b]n是的哦,搞半天来了,没有搞定。rnrn输出的SQL是正常的。rn不是为什么哦?n[b]问题补充:[/b]n我用list试试n[b]问题补充:[/b]n怎么个用法,发端代码看看。n[b]问题补充:[/b]n还是不知道怎么解决哦?n[b]问题补充:[/b]n我先试试,问题先不关闭 问答

spring DAO泛型依赖注入

11-11

java.lang.IllegalStateException: Autowired annotation requires at least one argument: public void com.strogit.assetsmanagement.service.impl.AlarmServiceImpl.setAlarmDao()rn at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$2.doWith(AutowiredAnnotationBeanPostProcessor.java:307)rn at org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:466)rn at org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:443)rn at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.findAutowiringMetadata(AutowiredAnnotationBeanPostProcessor.java:299)rn at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessMergedBeanDefinition(AutowiredAnnotationBeanPostProcessor.java:179)rn at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyMergedBeanDefinitionPostProcessors(AbstractAutowireCapableBeanFactory.java:745)rn at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:448)rn at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)rn at java.security.AccessController.doPrivileged(Native Method)rn at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)rn at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)rn at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)rn at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)rn at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)rn at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)rn at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:429)rn at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:728)rn at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:380)rn at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:255)rn at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:199)rn at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:45)rn at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3934)rn at org.apache.catalina.core.StandardContext.start(StandardContext.java:4429)rn at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)rn at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)rn at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:526)rn at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.jrnrn怎么会出现这样的问题rnrnrn public BaseDAOImpl alarmDao;rn rn @Autowiredrn public void setAlarmDao() rn alarmDao=new BaseDAOImpl(Alarm.class);rn rnrn用的是注解配置rn 论坛

使用泛型DAO 报错!!?

09-06

rnrn代码如下:rnpackage com.flsoft.hgjlserver.orm;rnrnimport java.io.Serializable;rnrnpublic interface ITestDao rnrn public T findById(PK id);rnrnrn// 实现 :rnpackage com.flsoft.hgjlserver.ormImpl;rnrnimport java.io.Serializable;rnimport java.lang.reflect.ParameterizedType;rnimport java.lang.reflect.Type;rnrnimport org.springframework.orm.hibernate3.support.HibernateDaoSupport;rnrnimport com.flsoft.hgjlserver.orm.ITestDao;rnrnpublic class TestDao rnextends HibernateDaoSupport implements ITestDaornrn // 实体类类型(由构造方法自动赋值)rn private Class entityClass;rnrn // 构造方法,根据实例类自动获取实体类类型rn public TestDao() rn this.entityClass = null;rn Class c = getClass();rn Type t = c.getGenericSuperclass();rn if (t instanceof ParameterizedType) rn Type[] p = ((ParameterizedType) t).getActualTypeArguments();rn this.entityClass = (Class) p[0];rn rn rnrn public T findById(PK id) rn // TODO Auto-generated method stubrn return (T) getHibernateTemplate().get(entityClass, id);rn rnrn// 具体dao接口:rnpackage com.flsoft.hgjlserver.orm;rnrnimport com.flsoft.hgjlserver.module.Task;rnrnpublic interface ITaskTes extends ITestDaornrnrn// 它的实现:rnpackage com.flsoft.hgjlserver.ormImpl;rnrnimport org.springframework.context.ApplicationContext;rnimport org.springframework.context.support.FileSystemXmlApplicationContext;rnrnimport com.flsoft.hgjlserver.module.Task;rnimport com.flsoft.hgjlserver.orm.ITaskTes;rnimport com.flsoft.hgjlserver.orm.ITestDao;rnrnpublic class TaskTest extends TestDao implements ITaskTesrnrn ITestDao tdao;rn rn public static void main(String[] args) rn ApplicationContext ac = new FileSystemXmlApplicationContext(rn "E:/MyEclipseworkspace/HGJL/HGJLServerDao/src/test/resources/applicationContext.xml");rn ITaskTes taskTes = (ITaskTes) ac.getBean("TaskTest");rn System.out.println(taskTes.findById(new Long(49)).getTstate());rn rn rn public TaskTest()rn rn public Task findById(Long id) rn // TODO Auto-generated method stubrn return tdao.findById(id);rn rnrn public ITestDao getTdao() rn return tdao;rn rnrn public void setTdao(ITestDao tdao) rn this.tdao = tdao;rn rn rnrn[/code]rn//配置:rn[code=XML]rn rn rn rn rn rn rn rn rn rn rn rn [/code]rn报错误如下:rn[code=Java][DEBUG] [org.springframework.orm.hibernate3.SessionFactoryUtils.doGetSession(SessionFactoryUtils.java:316)] ctoryUtils - Opening Hibernate Sessionrn[DEBUG] [org.hibernate.impl.SessionImpl.(SessionImpl.java:220)] essionImpl - opened session at timestamp: 12837607548rn[DEBUG] [org.springframework.orm.hibernate3.SessionFactoryUtils.closeSession(SessionFactoryUtils.java:789)] ctoryUtils - Closing Hibernate SessionrnException in thread "main" java.lang.NullPointerExceptionrn at org.hibernate.impl.SessionImpl.get(SessionImpl.java:808)rn at org.springframework.orm.hibernate3.HibernateTemplate$1.doInHibernate(HibernateTemplate.java:519)rn at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:406)rn at org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374)rn at org.springframework.orm.hibernate3.HibernateTemplate.get(HibernateTemplate.java:512)rn at org.springframework.orm.hibernate3.HibernateTemplate.get(HibernateTemplate.java:506)[DEBUG] [org.hibernate.impl.SessionImpl.close(SessionImpl.java:273)] essionImpl - closing sessionrn[DEBUG] [org.hibernate.jdbc.ConnectionManager.cleanup(ConnectionManager.java:375)] ionManager - connection already null in cleanup : no actionrnrn at com.flsoft.hgjlserver.ormImpl.TestDao.findById(TestDao.java:30)rn at com.flsoft.hgjlserver.ormImpl.TaskTest.findById(TaskTest.java:25)rn at com.flsoft.hgjlserver.ormImpl.TaskTest.findById(TaskTest.java:1)rn at com.flsoft.hgjlserver.ormImpl.TaskTest.main(TaskTest.java:18)[/code]rnrn帮忙指点一下哪儿错了,是不是session没有给?rn谢谢!! 论坛

泛型DAO的问题

08-24

用了DAO,Spring 的AOP不起做用了.... n n 例子: n /** n *DAO定义最基本的save,delete,update,find..; n */ n public interface DAO n public void save(T t); n public void delete(T t); n public void update(T t); n public T findById(Integer id); n public List findAll(); n n n /** n * CustomerDAO 一个 DAO 的子类. n */ n public interface CustomerDAO extends DAO n //定义Customer特有的操作. n public Customer findByAddress(String address); n n n /* n *CustomerDAO 的一个实现. n */ n public class CustomerDAOImpl extends HibernateDaoSupport implements CustomerDAO n /** n *定义过的泛型参数都会被具体化. n */ n public void save(Customer t) n public void update(Customer t) n public void delete(Customer t) n n n n public Customer findById(Integer id) n public List findAll() n public Customer findByAddress(String address); n n n n 加入AOP对 CustomerDAO 的所有方法 进行日志记录. n 是泛型参数的AOP不起做用,如save,update,delete方法. n 不是泛型参数的AOP都可以起到做用. findById,findAll,findByAddress方法. n n n 当我修改DAO中的save方法为: n public void save(Object obj); n AOP就可以起到作用了. n n n 我不清楚是配置风格的问题(Spring 2.X风格),还是AOP与泛型不兼容. n 上面的结论是:只要是泛型参数,AOP不起作用. n n 写在后面: n 这里的DAO本身没有太大的作用,只是把最基本的操作放在最顶层,利用泛型参数转变有真实参数. n 写成这样的形式: n public interface DAO n public void save(Object obj); n public void update(Object obj); n ... n n 也可以,只是继承过来都是Object,少了显式类型. 问答

没有更多推荐了,返回首页