您的位置:首页 > 其它

通用Dao 设计 2

2013-07-16 11:25 162 查看
泛型是JDK1.5的一个新的特性,使用泛型机制编写的程序代码要比那些杂乱的使用Object变量,然后再进行强制类型转换的代码具有更好的安全性和可读性。如果你的系统运行在JDK1.5以上的版本上,建议多使用泛型来代替无休止的对象转换。
在软件设计中我们开始对系统进行三层甚至是多层架构了,目的是职责更加的明确,功能更加的分离。而常常使用的三层架构就是将表现层、业务逻辑层和持久层进行分离,每一层关注点不同,职能更加的清晰。所以DAO的设计模式现在已经被我们所接受,下面就介绍一下泛型DAO的设计和实现。

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

通用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()是调用hibernate的load方法------------




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();






/** *//***************************************************************************


* --------------------------------相关知识炿--------------------------------*


*


* 1、Session的load方法和get方法都是通过给定的ID从数据库中加载一个持久化的对象㿂但两个斿*


* 法的区别在于:当数据库不存在于ID对应的记录时,load()方法抛出异常,迌get()方法返回null*


***************************************************************************/




}



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

通用Hibernate 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();


}






/** *//**


* 该实现没有实现加锁删除对象的操作,在spring的DAO实现中已经实玿


*/




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();


}




// 该实现没有实现加锁的删除,在spring的dao中已经实现了




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();


}






/** *//**


* 注意:该方法是鿚过设置参数来进行命名查询,承以在传参数时,一定要注意paramNames和values的长度,位置要一丿对应〿


*/


@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, 0, 1);


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, 0, 1);


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中书写自己的逻辑代码,也让我们慢慢的建立自己业务逻辑层(在EJB,spring这样的框架没有引入的情况下)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: