基于hibernate的泛型Dao层设计

泛型是JDK1.5的一个新的特性,使用泛型机制编写的程序代码要比那些杂乱的使用Object变量,然后再进行强制类型转换的代码具有更好的安全性和可读性。如果你的系统运行在JDK1.5以上的版本上,建议多使用泛型来代替无休止的对象转换。

         在软件设计中我们开始对系统进行三层甚至是多层架构了,目的是职责更加的明确,功能更加的分离。而常常使用的三层架构就是将表现层、业务逻辑层和持久层进行分离,每一层关注点不同,职能更加的清晰。所以DAO的设计模式现在已经被我们所接受,下面就介绍一下泛型DAO的设计和实现。

         这次的DAO例子是基于接口的.很多工具Hibernate已经提供了数据库的便携访问,所以我们不是为持久层的轻便而设计接口然而, DAO接口在较为复杂的应用中更有意义当有几个持久化服务被封装到一个持久层的时候我想在很多情况下你应该直接使用Hibernate或者JPA, 而使用外加的DAO层最好的理由是为了实现更高的抽象化(例如:定义方法名findAll(String hql)而不是无数次地重复session.createQuery(...))

通用DAO接口:

package com.baiyyy.util.dao;

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

import org.hibernate.Criteria;
import org.hibernate.LockMode;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.DetachedCriteria;

/**
 承有业务数据的基础访问接口
 <p>
 承有CRUD (创建,读取,修改和删陿)基本数据的操作在这个接口中都是独立的_ 并且承有的DAO都可以使用这些基本实玿
 
 @author yongtree
 
 * @date:2008-03-04
 */
public interface IBaseDAO<T, ID extends Serializable> {

  /***************************************************************************
   * -------------------基本棿索增加修改删除操使---------------------------- *
   **************************************************************************/

  // --------findById()方法是get(ID id)得到实体对象-----------------------
  /**
   通过ID来得到实体对豿
   
   @param id
   *            实体对象的标识符
   @param lock
   *            使用的锁模式
   @return 该主键忼对应的实体对象
   */
  public T findById(ID id, LockMode lock);

  /**
   通过ID来得到实体对豿
   
   @param id
   @return T
   */
  public T findById(ID id);

  /**
   通过ID来得到实体对豿(为兼容其他开发成员的原有程序,保留使甿)
   
   @param c
   @param id
   @return T
   */
  public T findById(Class c, ID id);

  // -------------loadById()是调用hibernateload方法------------

  public T loadById(ID id);

  /**
   通过id load对象
   
   @param id
   @param lock
   @return
   */
  public T loadById(ID id, LockMode lock);

  /**
   获取全部的实使
   
   @return
   */
  public List<T> loadAll();

  /**
   保存丿个实体对豿
   
   @param entity
   */
  public T saveEntity(T entity);

  /**
   更新丿个实体对豿
   
   @param entity
   */
  public void updateEntity(T entity);

  public void updateEntity(T entity, LockMode lock);

  /**
   增加或更新集合中的全部实使
   
   @param entities
   */
  public void saveOrUpdateAll(Collection<T> entities);

  /**
   删除丿个实使
   
   @param entity
   @throws Exception
   */
  public void deleteEntity(T entity);

  public void deleteEntity(T entity, LockMode lock);

  /**
   根据主键删除指定实体
   
   @param id
   */
  public void deleteEntityById(ID id);

  public void deleteEntityById(ID id, LockMode lock);

  /**
   批量删除
   
   @param entities
   */
  public void deleteAll(Collection<T> entities);

  /**
   通过合并的方式更新对豿
   
   @param entity
   *            void
   */
  public void merge(T entity);

  /***************************************************************************
   * ------------------------------使用HQL语句-------------------------------- *
   **************************************************************************/

  /**
   使用HQL语句进行对象的查诿
   
   @param hsql
   *            查询语句
   @return 符合条件的对豿
   */

  public T getEntity(String hsql);

  /**
   使用HQL语句进行查询
   
   @param hsql
   *            查询语句
   @return 符合条件的对象集吿
   */
  public List<T> getEntities(String hsql);

  /**
   使用带参数的HQL语句进行查询
   
   @param hsql
   @param obj
   @return
   */
  public List<T> getEntities(String hsql, Object[] values);

  public List<T> getEntities(String hql, int start, int number);

  public List<T> getEntities(String hql, int start, int number,
      Object[] values);

  /**
   使用命名的HQL语句棿索数捿
   
   @param queryName
   @return
   */
  public List<T> findByNamedQuery(String queryName);

  /**
   使用带参数的命名HSQL语句棿索数捿
   
   @param queryName
   @param values
   @return
   */
  public List<T> findByNamedQuery(String queryName, Object[] values);

  /**
   使用带命名参数的命名HSQL语句棿索数捿
   
   @param queryName
   @param paramNames
   @param values
   @return
   */
  public List<T> findByNamedQuery(String queryName, String[] paramNames,
      Object[] values);

  /**
   使用HQL语句棿索数据,返回 Iterator
   
   @param queryString
   @return
   */
  public Iterator<T> iterate(String queryString);

  /**
   使用带参数HSQL语句棿索数据,返回 Iterator
   
   @param queryString
   @param values
   @return
   */
  public Iterator<T> iterate(String queryString, Object[] values);

  /***************************************************************************
   * -----------------------------Criteria动濁查诿---------------------------- *
   **************************************************************************/

  /**
   创建与会话无关的棿索标准对豿
   */
  public DetachedCriteria createDetachedCriteria();

  /**
   创建与会话绑定的棿索标准对豿
   
   @return
   */
  public Criteria createCriteria();

  /**
   使用指定的检索标准检索数捿
   
   @param criteria
   @return
   */
  public List<T> findByCriteria(DetachedCriteria criteria);

  /**
   使用指定的检索标准检索数据,返回部分记录
   
   @param criteria
   @param firstResult
   @param maxResults
   @return
   */
  public List<T> findByCriteria(DetachedCriteria criteria, int firstResult,
      int maxResults);

  /**
   通过动濁查询条件进行查诿
   
   @param criterion
   @return List<T>
   */
  @SuppressWarnings("unchecked")
  public List<T> findByCriteria(Criterion... criterion);

  /**
   使用指定的检索标准检索数据,返回指定范围的记彿
   
   @param criteria
   @return
   */
  public Integer getRowCount(DetachedCriteria criteria);

  /**
   使用指定的检索标准检索数据,返回指定统计倿
   
   @param criteria
   @param propertyName
   @param StatName
   *            (max,min,avg,sum)
   @return
   */
  public Object getStatValue(DetachedCriteria criteria, String propertyName,
      String StatName);

  /**
   通过给定的一个对象,查找与其匹配的对象,表关联比较多时,用户可以自己根据霿要扩展㿿
   
   @param entity
   @return List<T>
   */
  public List<T> findByExample(T entity);

  /***************************************************************************
   * -------------------------Others ----------------------------------------*
   **************************************************************************/

  /**
   加锁指定的实使
   
   @param entity
   @param lockMode
   */
  public void lock(T entity, LockMode lockMode);

  /**
   强制立即更新缓冲数据到数据库(否则仅在事务提交时才更新)
   */
  public void flush();

  /**
   清空缓存
   
   * void
   */
  public void clear();

  /***************************************************************************
   * --------------------------------相关知识炿--------------------------------*
   
   * 1Sessionload方法和get方法都是通过给定的ID从数据库中加载一个持久化的对象但两个斿*
   法的区别在于:当数据库不存在于ID对应的记录时,load()方法抛出异常,迌get()方法返回null*
   ***************************************************************************/

}

 

设计完接口,我们就要实现我们创建的接口,我们如果使用Hibernate,那么就做一个hibernate的实现,如果使用JPA,那么就做一个JPA实现。以下采用hibernate进行实现。

通用Hibernate DAO实现:

package com.baiyyy.util.dao;

/**
 * @filename:BaseHibernateDAO.java
 */

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

import org.hibernate.Criteria;
import org.hibernate.LockMode;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Example;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Projections;

import com.baiyyy.workflow.pojo.TWfPackage;

/**
 Hibernate实现通用DAO接口
 
 @author yongtree
 * @date 2008-3-10
 @param <T>
 @param <ID>
 */
public class BaseHibernateDAO<T, ID extends Serializable> implements
    IBaseDAO<T, ID> {
  // 保持实体对象类的类型
  private Class<T> persistentClass;

  private Session session;

  /**
   方泿
   */
  @SuppressWarnings("unchecked")
  public BaseHibernateDAO() {
    //下面这种方式丿直有错误,不能得到真正的T.class,迌是Object.class
    // this.persistentClass=GenericsUtils.getSuperClassGenricType(getClass());
    // System.out.println(obj.getClass().getName());
  }

  @SuppressWarnings("unchecked")
  public BaseHibernateDAO(Class clazz) {
    this.persistentClass = clazz;
  }

  /**
   @param session
   *            the session to set
   */
  public void setSession(Session session) {
    this.session = session;
  }

  /**
   得到当前线程的Session对象的实便
   
   @return
   */
  protected Session getSession() {
    System.out.println("get session");
    return HibernateUtil.getCurrentSession();
  }

  /**
   得到持久化对象的类型
   
   @return 持久化类的类垿
   */
  protected Class<T> getPersistentClass() {
    return persistentClass;
  }

  @SuppressWarnings("unchecked")
  public T findById(ID id, LockMode lock) {
    // TODO Auto-generated method stub
    T entity = (T) getSession().get(getPersistentClass(), id, lock);
    if (entity != null) {
      this.flush();
    }

    return entity;
  }

  @SuppressWarnings("unchecked")
  public T findById(Class c, ID id) {
    // TODO Auto-generated method stub
    T entity;

    entity = (T) getSession().get(c, id);

    return entity;
  }

  @SuppressWarnings("unchecked")
  public T findById(ID id) {
    // TODO Auto-generated method stub
    T entity = (T) getSession().get(getPersistentClass(), id);

    return entity;
  }

  @SuppressWarnings("unchecked")
  public T loadById(ID id) {
    // TODO Auto-generated method stub
    T entity = (T) getSession().load(getPersistentClass(), id);
    return entity;
  }

  @SuppressWarnings("unchecked")
  public T loadById(Class c, ID id) {
    // TODO Auto-generated method stub
    T entity = (T) getSession().load(c, id);
    return entity;
  }

  @SuppressWarnings("unchecked")
  public T loadById(ID id, LockMode lock) {
    // TODO Auto-generated method stub
    T entity = (T) getSession().load(getPersistentClass(), id, lock);
    return entity;
  }

  @SuppressWarnings("unchecked")
  public List<T> loadAll() {
    List<T> list = getSession().createQuery(
        "from " + getPersistentClass().getName()).list();
    return list;
  }

  public T saveEntity(T entity) {
    // TODO Auto-generated method stub

    getSession().save(entity);
    this.flush();
    return entity;
  }

  public void updateEntity(T entity) {
    // TODO Auto-generated method stub
    getSession().saveOrUpdate(entity);
    this.flush();
  }

  /**
   该实现类暂时没有实现更新加锁的操使
   */
  public void updateEntity(T entity, LockMode lock) {
    // TODO Auto-generated method stub
    getSession().saveOrUpdate(entity);
    this.flush();
  }

  public void saveOrUpdateAll(Collection<T> entities) {
    getSession().saveOrUpdate(entities);
    this.flush();
  }

  public void deleteEntity(T entity) {
    // TODO Auto-generated method stub
    getSession().delete(entity);
    this.flush();
  }

  /**
   该实现没有实现加锁删除对象的操作,在springDAO实现中已经实玿
   */
  public void deleteEntity(T entity, LockMode lock) {
    // TODO Auto-generated method stub
    getSession().delete(entity);
    this.flush();
  }

  public void deleteEntityById(ID id) {
    this.deleteEntity(this.loadById(id));
    this.flush();
  }

  // 该实现没有实现加锁的删除,在springdao中已经实现了
  public void deleteEntityById(ID id, LockMode lock) {
    this.deleteEntity(this.loadById(id));
    this.flush();
  }

  public void deleteAll(Collection<T> entities) {
    this.flush();
    getSession().delete(entities);
  }
  
  public void merge(T entity){
    getSession().merge(entity);
    this.flush();
  }

  @SuppressWarnings("unchecked")
  public T getEntity(String hsql) {
    T uniqueResult = (T) getSession().createQuery(hsql).uniqueResult();
    // TODO Auto-generated method stub
    return uniqueResult;
  }

  @SuppressWarnings("unchecked")
  public List<T> getEntities(String hsql) {
    // TODO Auto-generated method stub

    List list = getSession().createQuery(hsql).list();
    return list;
  }

  @SuppressWarnings("unchecked")
  public List<T> getEntities(String hql, int start, int number,
      Object[] values) {
    // TODO Auto-generated method stub
    Query query = getSession().createQuery(hql);
    for (int i = 0; i < values.length; i++) {
      query.setParameter(i, values[i]);
    }
    query.setFirstResult(start);
    query.setMaxResults(number);
    List list = query.list();
    return list;
  }

  @SuppressWarnings("unchecked")
  public List<T> getEntities(String hql, int start, int number) {
    // TODO Auto-generated method stub
    Query query = getSession().createQuery(hql);
    query.setFirstResult(start);
    query.setMaxResults(number);
    List list = query.list();
    return list;
  }

  @SuppressWarnings("unchecked")
  public List<T> getEntities(String hql, Object[] values) {
    // TODO Auto-generated method stub
    Query query = getSession().createQuery(hql);
    for (int i = 0; i < values.length; i++) {
      query.setParameter(i, values[i]);
    }
    return query.list();
  }

  @SuppressWarnings("unchecked")
  public List<T> findByNamedQuery(String queryName) {
    // TODO Auto-generated method stub
    return getSession().getNamedQuery(queryName).list();
  }

  @SuppressWarnings("unchecked")
  public List<T> findByNamedQuery(String queryName, Object[] values) {
    // TODO Auto-generated method stub
    Query query = getSession().getNamedQuery(queryName);
    for (int i = 0; i < values.length; i++) {
      query.setParameter(i, values);
    }
    return query.list();
  }

  /**
   注意:该方法是过设置参数来进行命名查询,承以在传参数时,一定要注意paramNamesvalues的长度,位置要一丿对应
   */
  @SuppressWarnings("unchecked")
  public List<T> findByNamedQuery(String queryName, String[] paramNames,
      Object[] values) {
    // TODO Auto-generated method stub
    Query query = getSession().getNamedQuery(queryName);
    for (int i = 0; i < paramNames.length; i++) {
      query.setParameter(paramNames[i], values[i]);
    }
    return query.list();
  }

  @SuppressWarnings("unchecked")
  public Iterator<T> iterate(String hql) {
    // TODO Auto-generated method stub
    return getSession().createQuery(hql).iterate();
  }

  @SuppressWarnings("unchecked")
  public Iterator<T> iterate(String hql, Object[] values) {
    // TODO Auto-generated method stub
    Query query = getSession().createQuery(hql);
    for (int i = 0; i < values.length; i++) {
      query.setParameter(i, values[i]);
    }
    return query.iterate();
  }

  public DetachedCriteria createDetachedCriteria() {
    // TODO Auto-generated method stub
    return DetachedCriteria.forClass(this.persistentClass);
  }

  public Criteria createCriteria() {
    // TODO Auto-generated method stub
    return this.createDetachedCriteria().getExecutableCriteria(
        this.getSession());
  }

  /**
   该方法没有经过验证,不能保证正确,在spring的实现中已经实现亿
   */
  @SuppressWarnings("unchecked")
  public List<T> findByCriteria(DetachedCriteria criteria) {
    // TODO Auto-generated method stub
    return criteria.getExecutableCriteria(this.getSession()).list();
  }

  @SuppressWarnings("unchecked")
  public List<T> findByCriteria(DetachedCriteria criteria, int firstResult,
      int maxResults) {
    // TODO Auto-generated method stub
    return criteria.getExecutableCriteria(this.getSession())
        .setFirstResult(firstResult).setMaxResults(maxResults).list();

  }

  /**
   动濁查诿
   
   @param criterion
   @return
   */
  public @SuppressWarnings("unchecked")
  List<T> findByCriteria(Criterion... criterion) {
    Criteria crit = getSession().createCriteria(getPersistentClass());
    for (Criterion c : criterion) {

      if (c != null) {

        crit.add(c);

      }
    }
    List list = crit.list();
    return list;
  }

  @SuppressWarnings("unchecked")
  public Integer getRowCount(DetachedCriteria criteria) {
    // TODO Auto-generated method stub
    criteria.setProjection(Projections.rowCount());
    List list = this.findByCriteria(criteria, 01);
    return (Integer) list.get(0);

  }

  @SuppressWarnings("unchecked")
  public Object getStatValue(DetachedCriteria criteria, String propertyName,
      String StatName) {
    // TODO Auto-generated method stub
    if (StatName.toLowerCase().equals("max"))
      criteria.setProjection(Projections.max(propertyName));
    else if (StatName.toLowerCase().equals("min"))
      criteria.setProjection(Projections.min(propertyName));
    else if (StatName.toLowerCase().equals("avg"))
      criteria.setProjection(Projections.avg(propertyName));
    else if (StatName.toLowerCase().equals("sum"))
      criteria.setProjection(Projections.sum(propertyName));
    else
      return null;
    List list = this.findByCriteria(criteria, 01);
    return list.get(0);
  }

  @SuppressWarnings("unchecked")
  public List<T> findByExample(T exampleInstance) {
    // TODO Auto-generated method stub
    Criteria crit = getSession().createCriteria(getPersistentClass());
    Example example = Example.create(exampleInstance);
    example.ignoreCase().enableLike(MatchMode.ANYWHERE);// 忽略大小写,并进行模糊比辿
    example.excludeZeroes();// 对于属濧中有数字类型的,如果exampleInstance的属性忼为0,就把它添加到查询中
    crit.add(example);
    return crit.list();

  }

  public void lock(T entity, LockMode lockMode) {
    // TODO Auto-generated method stub
    getSession().lock(entity, lockMode);
  }

  public void flush() {
    // TODO Auto-generated method stub
    getSession().flush();
  }

  public void clear() {
    // TODO Auto-generated method stub
    getSession().clear();
  }

}

到现在为止,Hibernate通用DAO已经建立完成,作为一个通用的工具类,我们希望每个实体DAO都能继承这个DAO。继续发扬接口编程,每一个持久化实体类我们都建立一个接口,并且让这些接口都继承IBaseDAO。

ParticipantDAO的写法:

public interface ParticipantDAO extends IBaseDAO<TWfParticipants, Integer>{
  //自定义该实体的接口
}

ParticipantDAO实现类的写法:

public class ParticipantDAOImpl extends
    BaseHibernateDAO<TWfParticipants, Integer> implements
    ParticipantDAO {

  public ParticipantDAOImpl() {
    super(TWfParticipants.class);
  }
   //实现自定义的方法
}

注:在BaseHibernateDAO的无参数构造函数中

 public BaseHibernateDAO() {
    //下面这种方式一直有错误,不能得到真正的T.class,迌是Object.class
    // this.persistentClass=GenericsUtils.getSuperClassGenricType(getClass());
  }
这种方式的写法在springside中使用过,但是自己调试始终有错误,始终无法得到T.class,得到的只是Oject.class,不知道怎么解决,还请高人指点。

以下是我的替代方法,可能不是太好。构建一个带有Class参数的构造函数,让每个DAO硬性传入class

public BaseHibernateDAO(Class clazz) {
    this.persistentClass = clazz;
  }
然后在子类DAO的构造参数中向父类传递一个class,因为一个DAO对应着一个实体,所以传入一个实体的class也是没有什么不可以的。

 public ParticipantDAOImpl() {
    super(TWfParticipants.class);
  }
补充GenericsUtils.java

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
   */
  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.
   */
  public static Class getSuperClassGenricType(Class clazz, int index)
      throws IndexOutOfBoundsException {

    Type genType = clazz.getGenericSuperclass();
//    Type genType = clazz;

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

    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];
  }
}

在实际的项目中,我们常常忽略了业务逻辑层,我们有人喜欢将大部分的逻辑放在表现层的Java Bean中,也有人喜欢在DAO中编写自己的业务逻辑,虽然功能都能实现,但是职责不明,让我们面对这些杂乱无章的代码,我们无所适从。泛型DAO的设计我感觉很大程度上可以强制程序员不要在DAO中书写自己的逻辑代码,也让我们慢慢的建立自己业务逻辑层(在EJBspring这样的框架没有引入的情况下)。

当然为了系统的可扩展性、可移植性和系统的松耦合,我们可以采用DAO工厂模式和反射机制来架构我们的系统,由于篇幅有限,这里就不做介绍了。这部分内容我将在以后的时间里进行整理并发布在我的csdn博客和javaeye博客上。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

赶路人儿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值