您的位置:首页 > 其它

基于hibernate的泛型Dao层设计

2015-01-19 18:40 267 查看
泛型是JDK1.5的一个新的特性,使用泛型机制编写的程序代码要比那些杂乱的使用Object变量,然后再进行强制类型转换的代码具有更好的安全性和可读性。如果你的系统运行在JDK1.5以上的版本上,建议多使用泛型来代替无休止的对象转换。
在软件设计中我们开始对系统进行三层甚至是多层架构了,目的是职责更加的明确,功能更加的分离。而常常使用的三层架构就是将表现层、业务逻辑层和持久层进行分离,每一层关注点不同,职能更加的清晰。所以DAO的设计模式现在已经被我们所接受,下面就介绍一下泛型DAO的设计和实现。
这次的DAO例子是基于接口的.很多工具,像Hibernate已经提供了数据库的便携访问,所以我们不是为持久层的轻便而设计接口.然而,
DAO接口在较为复杂的应用中更有意义,当有几个持久化服务被封装到一个持久层的时候,我想在很多情况下你应该直接使用Hibernate或者JPA,而使用外加的DAO层最好的理由是为了实现更高的抽象化(例如:定义方法名findAll(String
hql)而不是无数次地重复session.createQuery(...))
通用DAO接口:
packagecom.baiyyy.util.dao;

importjava.io.Serializable;

importjava.util.Collection;

importjava.util.Iterator;

importjava.util.List;

importorg.hibernate.Criteria;

importorg.hibernate.LockMode;

importorg.hibernate.criterion.Criterion;

importorg.hibernate.criterion.DetachedCriteria;

/**

*承有业务数据的基础访问接口

*<p>

*承有CRUD(创建,读取,修改和删陿)基本数据的操作在这个接口中都是独立的_并且承有的DAO都可以使用这些基本实玿

*

*@authoryongtree

*

*@date:2008-03-04

*/

publicinterfaceIBaseDAO<T,IDextendsSerializable>{

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

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

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

//--------findById()方法是鿚过get(IDid)得到实体对象-----------------------

/**

*通过ID来得到实体对豿

*

*@paramid

*实体对象的标识符

*@paramlock

*使用的锁模式

*@return该主键忼对应的实体对象

*/

publicTfindById(IDid,LockModelock);

/**

*通过ID来得到实体对豿

*

*@paramid

*@returnT

*/

publicTfindById(IDid);

/**

*通过ID来得到实体对豿(为兼容其他开发成员的原有程序,保留使甿)

*

*@paramc

*@paramid

*@returnT

*/

publicTfindById(Classc,IDid);

//-------------loadById()是调用hibernate的load方法------------

publicTloadById(IDid);

/**

*通过idload对象

*

*@paramid

*@paramlock

*@return

*/

publicTloadById(IDid,LockModelock);

/**

*获取全部的实使

*

*@return

*/

publicList<T>loadAll();

/**

*保存丿个实体对豿

*

*@paramentity

*/

publicTsaveEntity(Tentity);

/**

*更新丿个实体对豿

*

*@paramentity

*/

publicvoidupdateEntity(Tentity);

publicvoidupdateEntity(Tentity,LockModelock);

/**

*增加或更新集合中的全部实使

*

*@paramentities

*/

publicvoidsaveOrUpdateAll(Collection<T>entities);

/**

*删除丿个实使

*

*@paramentity

*@throwsException

*/

publicvoiddeleteEntity(Tentity);

publicvoiddeleteEntity(Tentity,LockModelock);

/**

*根据主键删除指定实体

*

*@paramid

*/

publicvoiddeleteEntityById(IDid);

publicvoiddeleteEntityById(IDid,LockModelock);

/**

*批量删除

*

*@paramentities

*/

publicvoiddeleteAll(Collection<T>entities);

/**

*通过合并的方式更新对豿

*

*@paramentity

*void

*/

publicvoidmerge(Tentity);

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

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

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

/**

*使用HQL语句进行对象的查诿

*

*@paramhsql

*查询语句

*@return符合条件的对豿

*/

publicTgetEntity(Stringhsql);

/**

*使用HQL语句进行查询

*

*@paramhsql

*查询语句

*@return符合条件的对象集吿

*/

publicList<T>getEntities(Stringhsql);

/**

*使用带参数的HQL语句进行查询

*

*@paramhsql

*@paramobj

*@return

*/

publicList<T>getEntities(Stringhsql,Object[]values);

publicList<T>getEntities(Stringhql,intstart,intnumber);

publicList<T>getEntities(Stringhql,intstart,intnumber,

Object[]values);

/**

*使用命名的HQL语句棿索数捿

*

*@paramqueryName

*@return

*/

publicList<T>findByNamedQuery(StringqueryName);

/**

*使用带参数的命名HSQL语句棿索数捿

*

*@paramqueryName

*@paramvalues

*@return

*/

publicList<T>findByNamedQuery(StringqueryName,Object[]values);

/**

*使用带命名参数的命名HSQL语句棿索数捿

*

*@paramqueryName

*@paramparamNames

*@paramvalues

*@return

*/

publicList<T>findByNamedQuery(StringqueryName,String[]paramNames,

Object[]values);

/**

*使用HQL语句棿索数据,返回Iterator

*

*@paramqueryString

*@return

*/

publicIterator<T>iterate(StringqueryString);

/**

*使用带参数HSQL语句棿索数据,返回Iterator

*

*@paramqueryString

*@paramvalues

*@return

*/

publicIterator<T>iterate(StringqueryString,Object[]values);

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

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

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

/**

*创建与会话无关的棿索标准对豿

*/

publicDetachedCriteriacreateDetachedCriteria();

/**

*创建与会话绑定的棿索标准对豿

*

*@return

*/

publicCriteriacreateCriteria();

/**

*使用指定的检索标准检索数捿

*

*@paramcriteria

*@return

*/

publicList<T>findByCriteria(DetachedCriteriacriteria);

/**

*使用指定的检索标准检索数据,返回部分记录

*

*@paramcriteria

*@paramfirstResult

*@parammaxResults

*@return

*/

publicList<T>findByCriteria(DetachedCriteriacriteria,intfirstResult,

intmaxResults);

/**

*通过动濁查询条件进行查诿

*

*@paramcriterion

*@returnList<T>

*/

@SuppressWarnings("unchecked")

publicList<T>findByCriteria(Criterion...criterion);

/**

*使用指定的检索标准检索数据,返回指定范围的记彿

*

*@paramcriteria

*@return

*/

publicIntegergetRowCount(DetachedCriteriacriteria);

/**

*使用指定的检索标准检索数据,返回指定统计倿

*

*@paramcriteria

*@parampropertyName

*@paramStatName

*(max,min,avg,sum)

*@return

*/

publicObjectgetStatValue(DetachedCriteriacriteria,StringpropertyName,

StringStatName);

/**

*通过给定的一个对象,查找与其匹配的对象,表关联比较多时,用户可以自己根据霿要扩展㿿

*

*@paramentity

*@returnList<T>

*/

publicList<T>findByExample(Tentity);

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

*-------------------------Others----------------------------------------*

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

/**

*加锁指定的实使

*

*@paramentity

*@paramlockMode

*/

publicvoidlock(Tentity,LockModelockMode);

/**

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

*/

publicvoidflush();

/**

*清空缓存

*

*void

*/

publicvoidclear();

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

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

*

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

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

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

}

设计完接口,我们就要实现我们创建的接口,我们如果使用Hibernate,那么就做一个hibernate的实现,如果使用JPA,那么就做一个JPA实现。以下采用hibernate进行实现。
通用HibernateDAO实现:
packagecom.baiyyy.util.dao;

/**

*@filename:BaseHibernateDAO.java

*/

importjava.io.Serializable;

importjava.util.Collection;

importjava.util.Iterator;

importjava.util.List;

importorg.hibernate.Criteria;

importorg.hibernate.LockMode;

importorg.hibernate.Query;

importorg.hibernate.Session;

importorg.hibernate.criterion.Criterion;

importorg.hibernate.criterion.DetachedCriteria;

importorg.hibernate.criterion.Example;

importorg.hibernate.criterion.MatchMode;

importorg.hibernate.criterion.Projections;

importcom.baiyyy.workflow.pojo.TWfPackage;

/**

*用Hibernate实现通用DAO接口

*

*@authoryongtree

*@date2008-3-10

*@param<T>

*@param<ID>

*/

publicclassBaseHibernateDAO<T,IDextendsSerializable>implements

IBaseDAO<T,ID>{

//保持实体对象类的类型

privateClass<T>persistentClass;

privateSessionsession;

/**

*构鿠方泿

*/

@SuppressWarnings("unchecked")

publicBaseHibernateDAO(){

//下面这种方式丿直有错误,不能得到真正的T.class,迌是Object.class

//this.persistentClass=GenericsUtils.getSuperClassGenricType(getClass());

//System.out.println(obj.getClass().getName());

}

@SuppressWarnings("unchecked")

publicBaseHibernateDAO(Classclazz){

this.persistentClass=clazz;

}

/**

*@paramsession

*thesessiontoset

*/

publicvoidsetSession(Sessionsession){

this.session=session;

}

/**

*得到当前线程的Session对象的实便

*

*@return

*/

protectedSessiongetSession(){

System.out.println("getsession");

returnHibernateUtil.getCurrentSession();

}

/**

*得到持久化对象的类型

*

*@return持久化类的类垿

*/

protectedClass<T>getPersistentClass(){

returnpersistentClass;

}

@SuppressWarnings("unchecked")

publicTfindById(IDid,LockModelock){

//TODOAuto-generatedmethodstub

Tentity=(T)getSession().get(getPersistentClass(),id,lock);

if(entity!=null){

this.flush();

}

returnentity;

}

@SuppressWarnings("unchecked")

publicTfindById(Classc,IDid){

//TODOAuto-generatedmethodstub

Tentity;

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

returnentity;

}

@SuppressWarnings("unchecked")

publicTfindById(IDid){

//TODOAuto-generatedmethodstub

Tentity=(T)getSession().get(getPersistentClass(),id);

returnentity;

}

@SuppressWarnings("unchecked")

publicTloadById(IDid){

//TODOAuto-generatedmethodstub

Tentity=(T)getSession().load(getPersistentClass(),id);

returnentity;

}

@SuppressWarnings("unchecked")

publicTloadById(Classc,IDid){

//TODOAuto-generatedmethodstub

Tentity=(T)getSession().load(c,id);

returnentity;

}

@SuppressWarnings("unchecked")

publicTloadById(IDid,LockModelock){

//TODOAuto-generatedmethodstub

Tentity=(T)getSession().load(getPersistentClass(),id,lock);

returnentity;

}

@SuppressWarnings("unchecked")

publicList<T>loadAll(){

List<T>list=getSession().createQuery(

"from"+getPersistentClass().getName()).list();

returnlist;

}

publicTsaveEntity(Tentity){

//TODOAuto-generatedmethodstub

getSession().save(entity);

this.flush();

returnentity;

}

publicvoidupdateEntity(Tentity){

//TODOAuto-generatedmethodstub

getSession().saveOrUpdate(entity);

this.flush();

}

/**

*该实现类暂时没有实现更新加锁的操使

*/

publicvoidupdateEntity(Tentity,LockModelock){

//TODOAuto-generatedmethodstub

getSession().saveOrUpdate(entity);

this.flush();

}

publicvoidsaveOrUpdateAll(Collection<T>entities){

getSession().saveOrUpdate(entities);

this.flush();

}

publicvoiddeleteEntity(Tentity){

//TODOAuto-generatedmethodstub

getSession().delete(entity);

this.flush();

}

/**

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

*/

publicvoiddeleteEntity(Tentity,LockModelock){

//TODOAuto-generatedmethodstub

getSession().delete(entity);

this.flush();

}

publicvoiddeleteEntityById(IDid){

this.deleteEntity(this.loadById(id));

this.flush();

}

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

publicvoiddeleteEntityById(IDid,LockModelock){

this.deleteEntity(this.loadById(id));

this.flush();

}

publicvoiddeleteAll(Collection<T>entities){

this.flush();

getSession().delete(entities);

}



publicvoidmerge(Tentity){

getSession().merge(entity);

this.flush();

}

@SuppressWarnings("unchecked")

publicTgetEntity(Stringhsql){

TuniqueResult=(T)getSession().createQuery(hsql).uniqueResult();

//TODOAuto-generatedmethodstub

returnuniqueResult;

}

@SuppressWarnings("unchecked")

publicList<T>getEntities(Stringhsql){

//TODOAuto-generatedmethodstub

Listlist=getSession().createQuery(hsql).list();

returnlist;

}

@SuppressWarnings("unchecked")

publicList<T>getEntities(Stringhql,intstart,intnumber,

Object[]values){

//TODOAuto-generatedmethodstub

Queryquery=getSession().createQuery(hql);

for(inti=0;i<values.length;i++){

query.setParameter(i,values[i]);

}

query.setFirstResult(start);

query.setMaxResults(number);

Listlist=query.list();

returnlist;

}

@SuppressWarnings("unchecked")

publicList<T>getEntities(Stringhql,intstart,intnumber){

//TODOAuto-generatedmethodstub

Queryquery=getSession().createQuery(hql);

query.setFirstResult(start);

query.setMaxResults(number);

Listlist=query.list();

returnlist;

}

@SuppressWarnings("unchecked")

publicList<T>getEntities(Stringhql,Object[]values){

//TODOAuto-generatedmethodstub

Queryquery=getSession().createQuery(hql);

for(inti=0;i<values.length;i++){

query.setParameter(i,values[i]);

}

returnquery.list();

}

@SuppressWarnings("unchecked")

publicList<T>findByNamedQuery(StringqueryName){

//TODOAuto-generatedmethodstub

returngetSession().getNamedQuery(queryName).list();

}

@SuppressWarnings("unchecked")

publicList<T>findByNamedQuery(StringqueryName,Object[]values){

//TODOAuto-generatedmethodstub

Queryquery=getSession().getNamedQuery(queryName);

for(inti=0;i<values.length;i++){

query.setParameter(i,values);

}

returnquery.list();

}

/**

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

*/

@SuppressWarnings("unchecked")

publicList<T>findByNamedQuery(StringqueryName,String[]paramNames,

Object[]values){

//TODOAuto-generatedmethodstub

Queryquery=getSession().getNamedQuery(queryName);

for(inti=0;i<paramNames.length;i++){

query.setParameter(paramNames[i],values[i]);

}

returnquery.list();

}

@SuppressWarnings("unchecked")

publicIterator<T>iterate(Stringhql){

//TODOAuto-generatedmethodstub

returngetSession().createQuery(hql).iterate();

}

@SuppressWarnings("unchecked")

publicIterator<T>iterate(Stringhql,Object[]values){

//TODOAuto-generatedmethodstub

Queryquery=getSession().createQuery(hql);

for(inti=0;i<values.length;i++){

query.setParameter(i,values[i]);

}

returnquery.iterate();

}

publicDetachedCriteriacreateDetachedCriteria(){

//TODOAuto-generatedmethodstub

returnDetachedCriteria.forClass(this.persistentClass);

}

publicCriteriacreateCriteria(){

//TODOAuto-generatedmethodstub

returnthis.createDetachedCriteria().getExecutableCriteria(

this.getSession());

}

/**

*该方法没有经过验证,不能保证正确,在spring的实现中已经实现亿

*/

@SuppressWarnings("unchecked")

publicList<T>findByCriteria(DetachedCriteriacriteria){

//TODOAuto-generatedmethodstub

returncriteria.getExecutableCriteria(this.getSession()).list();

}

@SuppressWarnings("unchecked")

publicList<T>findByCriteria(DetachedCriteriacriteria,intfirstResult,

intmaxResults){

//TODOAuto-generatedmethodstub

returncriteria.getExecutableCriteria(this.getSession())

.setFirstResult(firstResult).setMaxResults(maxResults).list();

}

/**

*动濁查诿

*

*@paramcriterion

*@return

*/

public@SuppressWarnings("unchecked")

List<T>findByCriteria(Criterion...criterion){

Criteriacrit=getSession().createCriteria(getPersistentClass());

for(Criterionc:criterion){

if(c!=null){

crit.add(c);

}

}

Listlist=crit.list();

returnlist;

}

@SuppressWarnings("unchecked")

publicIntegergetRowCount(DetachedCriteriacriteria){

//TODOAuto-generatedmethodstub

criteria.setProjection(Projections.rowCount());

Listlist=this.findByCriteria(criteria,0,1);

return(Integer)list.get(0);

}

@SuppressWarnings("unchecked")

publicObjectgetStatValue(DetachedCriteriacriteria,StringpropertyName,

StringStatName){

//TODOAuto-generatedmethodstub

if(StatName.toLowerCase().equals("max"))

criteria.setProjection(Projections.max(propertyName));

elseif(StatName.toLowerCase().equals("min"))

criteria.setProjection(Projections.min(propertyName));

elseif(StatName.toLowerCase().equals("avg"))

criteria.setProjection(Projections.avg(propertyName));

elseif(StatName.toLowerCase().equals("sum"))

criteria.setProjection(Projections.sum(propertyName));

else

returnnull;

Listlist=this.findByCriteria(criteria,0,1);

returnlist.get(0);

}

@SuppressWarnings("unchecked")

publicList<T>findByExample(TexampleInstance){

//TODOAuto-generatedmethodstub

Criteriacrit=getSession().createCriteria(getPersistentClass());

Exampleexample=Example.create(exampleInstance);

example.ignoreCase().enableLike(MatchMode.ANYWHERE);//忽略大小写,并进行模糊比辿

example.excludeZeroes();//对于属濧中有数字类型的,如果exampleInstance的属性忼为0,就把它添加到查询中

crit.add(example);

returncrit.list();

}

publicvoidlock(Tentity,LockModelockMode){

//TODOAuto-generatedmethodstub

getSession().lock(entity,lockMode);

}

publicvoidflush(){

//TODOAuto-generatedmethodstub

getSession().flush();

}

publicvoidclear(){

//TODOAuto-generatedmethodstub

getSession().clear();

}

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

publicinterface
ParticipantDAO
extends
IBaseDAO<TWfParticipants,Integer>{


//自定义该实体的接口

}

ParticipantDAO
实现类的写法:

publicclass
ParticipantDAOImpl
extends


BaseHibernateDAO<TWfParticipants,Integer>implements


ParticipantDAO{


publicParticipantDAOImpl(){


super(TWfParticipants.class);


}


//实现自定义的方法

}

注:在BaseHibernateDAO的无参数构造函数中
publicBaseHibernateDAO(){

//下面这种方式一直有错误,不能得到真正的T.class,迌是Object.class

//this.persistentClass=GenericsUtils.getSuperClassGenricType(getClass());

}

这种方式的写法在springside中使用过,但是自己调试始终有错误,始终无法得到T.class,得到的只是Oject.class,不知道怎么解决,还请高人指点。
以下是我的替代方法,可能不是太好。构建一个带有Class参数的构造函数,让每个DAO硬性传入class。
publicBaseHibernateDAO(Classclazz){

this.persistentClass=clazz;

}

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


super(TWfParticipants.class);


}


补充GenericsUtils.java:
publicclass
GenericsUtils{


privatestaticfinalLoglog=LogFactory.getLog(GenericsUtils.class);


privateGenericsUtils(){


}


/**


*
通过反射
,
获得定义
Class
时声明的父类的范型参数的类型
.
publicBookManagerextendsGenricManager
<Book>


*


*@paramclazz


*Theclasstointrospect


*@returnthefirstgenericdeclaration,or<code>Object.class</code>if


*cannotbedetermined


*/


publicstaticClassgetSuperClassGenricType(Classclazz){


returngetSuperClassGenricType(clazz,0);


}


/**


*
通过反射
,
获得定义
Class
时声明的父类的范型参数的类型
.
publicBookManagerextendsGenricManager
<Book>


*


*@paramclazz


*clazzTheclasstointrospect


*@paramindex


*theIndexofthegenericddeclaration,startfrom0.


*/


publicstaticClassgetSuperClassGenricType(Classclazz,intindex)


throwsIndexOutOfBoundsException{


TypegenType=clazz.getGenericSuperclass();


//TypegenType=clazz;


if(!(genTypeinstanceofParameterizedType)){


log.warn(clazz.getSimpleName()


+"'ssuperclassnotParameterizedType");


returnclazz;


}


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


if(index>=params.length||index<0){


log.warn("Index:"+index+",Sizeof"+clazz.getSimpleName()


+"'sParameterizedType:"+params.length);


returnObject.class;


}


if(!(params[index]instanceofClass)){


log


.warn(clazz.getSimpleName()


+"notsettheactualclassonsuperclassgenericparameter");


returnObject.class;


}


return(Class)params[index];


}


}

在实际的项目中,我们常常忽略了业务逻辑层,我们有人喜欢将大部分的逻辑放在表现层的JavaBean中,也有人喜欢在DAO中编写自己的业务逻辑,虽然功能都能实现,但是职责不明,让我们面对这些杂乱无章的代码,我们无所适从。泛型DAO的设计我感觉很大程度上可以强制程序员不要在DAO中书写自己的逻辑代码,也让我们慢慢的建立自己业务逻辑层(在EJB,spring这样的框架没有引入的情况下)。
当然为了系统的可扩展性、可移植性和系统的松耦合,我们可以采用DAO工厂模式和反射机制来架构我们的系统,由于篇幅有限,这里就不做介绍了。这部分内容我将在以后的时间里进行整理并发布在我的csdn博客和javaeye博客上。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: