编写Spring+Hibernate框架下的应用,总是离不了编写一个通用的泛型GenericHibernateDao。查阅了网上不少的GenericHibernateDao实现,归纳整理为如下实现,供后续编码参考。
首先定义接口泛型DAO接口 GenericDao
package
com.th.huz;
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.DetachedCriteria;
/**
*
*
@author
lny
*/
public
interface
GenericDao
<
T
extends
Serializable,PK
extends
Serializable
>
{
//
--------------------基本检索、增加、修改、删除操作--------------------
//
根据主键获取实体。如果没有相应的实体,返回null。
public
Tget(PKid);
//
根据主键获取实体并加锁。如果没有相应的实体,返回null。
public
TgetWithLock(PKid,LockModelock);
//
根据主键获取实体。如果没有相应的实体,抛出异常。
public
Tload(PKid);
//
根据主键获取实体并加锁。如果没有相应的实体,抛出异常。
public
TloadWithLock(PKid,LockModelock);
//
获取全部实体。
public
List
<
T
>
loadAll();
//
loadAllWithLock()?
//
更新实体
public
void
update(Tentity);
//
更新实体并加锁
public
void
updateWithLock(Tentity,LockModelock);
//
存储实体到数据库
public
void
save(Tentity);
//
saveWithLock()
//
增加或更新实体
public
void
saveOrUpdate(Tentity);
//
增加或更新集合中的全部实体
public
void
saveOrUpdateAll(Collection
<
T
>
entities);
//
删除指定的实体
public
void
delete(Tentity);
//
加锁并删除指定的实体
public
void
deleteWithLock(Tentity,LockModelock);
//
根据主键删除指定实体
public
void
deleteByKey(PKid);
//
根据主键加锁并删除指定的实体
public
void
deleteByKeyWithLock(PKid,LockModelock);
//
删除集合中的全部实体
public
void
deleteAll(Collection
<
T
>
entities);
//
--------------------HSQL----------------------------------------------
//
使用HSQL语句直接增加、更新、删除实体
public
int
bulkUpdate(StringqueryString);
//
使用带参数的HSQL语句增加、更新、删除实体
public
int
bulkUpdate(StringqueryString,Object[]values);
//
使用HSQL语句检索数据
public
Listfind(StringqueryString);
//
使用带参数的HSQL语句检索数据
public
Listfind(StringqueryString,Object[]values);
//
使用带命名的参数的HSQL语句检索数据
public
ListfindByNamedParam(StringqueryString,String[]paramNames,
Object[]values);
//
使用命名的HSQL语句检索数据
public
ListfindByNamedQuery(StringqueryName);
//
使用带参数的命名HSQL语句检索数据
public
ListfindByNamedQuery(StringqueryName,Object[]values);
//
使用带命名参数的命名HSQL语句检索数据
public
ListfindByNamedQueryAndNamedParam(StringqueryName,
String[]paramNames,Object[]values);
//
使用HSQL语句检索数据,返回Iterator
public
Iteratoriterate(StringqueryString);
//
使用带参数HSQL语句检索数据,返回Iterator
public
Iteratoriterate(StringqueryString,Object[]values);
//
关闭检索返回的Iterator
public
void
closeIterator(Iteratorit);
//
--------------------------------Criteria------------------------------
//
创建与会话无关的检索标准对象
public
DetachedCriteriacreateDetachedCriteria();
//
创建与会话绑定的检索标准对象
public
CriteriacreateCriteria();
//
使用指定的检索标准检索数据
public
ListfindByCriteria(DetachedCriteriacriteria);
//
使用指定的检索标准检索数据,返回部分记录
public
ListfindByCriteria(DetachedCriteriacriteria,
int
firstResult,
int
maxResults);
//
使用指定的实体及属性检索(满足除主键外属性=实体值)数据
public
List
<
T
>
findEqualByEntity(Tentity,String[]propertyNames);
//
使用指定的实体及属性(非主键)检索(满足属性like串实体值)数据
public
List
<
T
>
findLikeByEntity(Tentity,String[]propertyNames);
//
使用指定的检索标准检索数据,返回指定范围的记录
public
IntegergetRowCount(DetachedCriteriacriteria);
//
使用指定的检索标准检索数据,返回指定统计值
public
ObjectgetStatValue(DetachedCriteriacriteria,StringpropertyName,
StringStatName);
//
--------------------------------Others--------------------------------
//
加锁指定的实体
public
void
lock(Tentity,LockModelockMode);
//
强制初始化指定的实体
public
void
initialize(Objectproxy);
//
强制立即更新缓冲数据到数据库(否则仅在事务提交时才更新)
public
void
flush();
}
实现GenericDao接口的Hibernate的实现类 GenericHibernateDao
package
com.th.huz;
import
java.io.Serializable;
import
java.lang.reflect.ParameterizedType;
import
java.lang.reflect.Type;
import
java.util.Collection;
import
java.util.Iterator;
import
java.util.List;
import
org.apache.commons.beanutils.PropertyUtils;
import
org.hibernate.Criteria;
import
org.hibernate.LockMode;
import
org.hibernate.criterion.DetachedCriteria;
import
org.hibernate.criterion.Example;
import
org.hibernate.criterion.MatchMode;
import
org.hibernate.criterion.Order;
import
org.hibernate.criterion.Projections;
import
org.hibernate.criterion.Restrictions;
import
org.springframework.orm.hibernate3.support.HibernateDaoSupport;
/**
*GenericHibernateDao继承HibernateDao,简单封装HibernateTemplate各项功能,
*简化基于HibernateDao的编写。
*
*
@author
lny
*/
@SuppressWarnings(
"
unchecked
"
)
public
class
GenericHibernateDao
<
T
extends
Serializable,PK
extends
Serializable
>
extends
HibernateDaoSupport
implements
GenericDao
<
T,PK
>
{
//
实体类类型(由构造方法自动赋值)
private
Class
<
T
>
entityClass;
//
构造方法,根据实例类自动获取实体类类型
public
GenericHibernateDao(){
this
.entityClass
=
null
;
Classc
=
getClass();
Typet
=
c.getGenericSuperclass();
if
(t
instanceof
ParameterizedType){
Type[]p
=
((ParameterizedType)t).getActualTypeArguments();
this
.entityClass
=
(Class
<
T
>
)p[
0
];
}
}
//
--------------------基本检索、增加、修改、删除操作--------------------
//
根据主键获取实体。如果没有相应的实体,返回null。
public
Tget(PKid){
return
(T)getHibernateTemplate().get(entityClass,id);
}
//
根据主键获取实体并加锁。如果没有相应的实体,返回null。
public
TgetWithLock(PKid,LockModelock){
Tt
=
(T)getHibernateTemplate().get(entityClass,id,lock);
if
(t
!=
null
){
this
.flush();
//
立即刷新,否则锁不会生效。
}
return
t;
}
//
根据主键获取实体。如果没有相应的实体,抛出异常。
public
Tload(PKid){
return
(T)getHibernateTemplate().load(entityClass,id);
}
//
根据主键获取实体并加锁。如果没有相应的实体,抛出异常。
public
TloadWithLock(PKid,LockModelock){
Tt
=
(T)getHibernateTemplate().load(entityClass,id,lock);
if
(t
!=
null
){
this
.flush();
//
立即刷新,否则锁不会生效。
}
return
t;
}
//
获取全部实体。
public
List
<
T
>
loadAll(){
return
(List
<
T
>
)getHibernateTemplate().loadAll(entityClass);
}
//
loadAllWithLock()?
//
更新实体
public
void
update(Tentity){
getHibernateTemplate().update(entity);
}
//
更新实体并加锁
public
void
updateWithLock(Tentity,LockModelock){
getHibernateTemplate().update(entity,lock);
this
.flush();
//
立即刷新,否则锁不会生效。
}
//
存储实体到数据库
public
void
save(Tentity){
getHibernateTemplate().save(entity);
}
//
saveWithLock()?
//
增加或更新实体
public
void
saveOrUpdate(Tentity){
getHibernateTemplate().saveOrUpdate(entity);
}
//
增加或更新集合中的全部实体
public
void
saveOrUpdateAll(Collection
<
T
>
entities){
getHibernateTemplate().saveOrUpdateAll(entities);
}
//
删除指定的实体
public
void
delete(Tentity){
getHibernateTemplate().delete(entity);
}
//
加锁并删除指定的实体
public
void
deleteWithLock(Tentity,LockModelock){
getHibernateTemplate().delete(entity,lock);
this
.flush();
//
立即刷新,否则锁不会生效。
}
//
根据主键删除指定实体
public
void
deleteByKey(PKid){
this
.delete(
this
.load(id));
}
//
根据主键加锁并删除指定的实体
public
void
deleteByKeyWithLock(PKid,LockModelock){
this
.deleteWithLock(
this
.load(id),lock);
}
//
删除集合中的全部实体
public
void
deleteAll(Collection
<
T
>
entities){
getHibernateTemplate().deleteAll(entities);
}
//
--------------------HSQL----------------------------------------------
//
使用HSQL语句直接增加、更新、删除实体
public
int
bulkUpdate(StringqueryString){
return
getHibernateTemplate().bulkUpdate(queryString);
}
//
使用带参数的HSQL语句增加、更新、删除实体
public
int
bulkUpdate(StringqueryString,Object[]values){
return
getHibernateTemplate().bulkUpdate(queryString,values);
}
//
使用HSQL语句检索数据
public
Listfind(StringqueryString){
return
getHibernateTemplate().find(queryString);
}
//
使用带参数的HSQL语句检索数据
public
Listfind(StringqueryString,Object[]values){
return
getHibernateTemplate().find(queryString,values);
}
//
使用带命名的参数的HSQL语句检索数据
public
ListfindByNamedParam(StringqueryString,String[]paramNames,
Object[]values){
return
getHibernateTemplate().findByNamedParam(queryString,paramNames,
values);
}
//
使用命名的HSQL语句检索数据
public
ListfindByNamedQuery(StringqueryName){
return
getHibernateTemplate().findByNamedQuery(queryName);
}
//
使用带参数的命名HSQL语句检索数据
public
ListfindByNamedQuery(StringqueryName,Object[]values){
return
getHibernateTemplate().findByNamedQuery(queryName,values);
}
//
使用带命名参数的命名HSQL语句检索数据
public
ListfindByNamedQueryAndNamedParam(StringqueryName,
String[]paramNames,Object[]values){
return
getHibernateTemplate().findByNamedQueryAndNamedParam(queryName,
paramNames,values);
}
//
使用HSQL语句检索数据,返回Iterator
public
Iteratoriterate(StringqueryString){
return
getHibernateTemplate().iterate(queryString);
}
//
使用带参数HSQL语句检索数据,返回Iterator
public
Iteratoriterate(StringqueryString,Object[]values){
return
getHibernateTemplate().iterate(queryString,values);
}
//
关闭检索返回的Iterator
public
void
closeIterator(Iteratorit){
getHibernateTemplate().closeIterator(it);
}
//
--------------------------------Criteria------------------------------
//
创建与会话无关的检索标准
public
DetachedCriteriacreateDetachedCriteria(){
return
DetachedCriteria.forClass(
this
.entityClass);
}
//
创建与会话绑定的检索标准
public
CriteriacreateCriteria(){
return
this
.createDetachedCriteria().getExecutableCriteria(
this
.getSession());
}
//
检索满足标准的数据
public
ListfindByCriteria(DetachedCriteriacriteria){
return
getHibernateTemplate().findByCriteria(criteria);
}
//
检索满足标准的数据,返回指定范围的记录
public
ListfindByCriteria(DetachedCriteriacriteria,
int
firstResult,
int
maxResults){
return
getHibernateTemplate().findByCriteria(criteria,firstResult,
maxResults);
}
//
使用指定的实体及属性检索(满足除主键外属性=实体值)数据
public
List
<
T
>
findEqualByEntity(Tentity,String[]propertyNames){
Criteriacriteria
=
this
.createCriteria();
Exampleexam
=
Example.create(entity);
exam.excludeZeroes();
String[]defPropertys
=
getSessionFactory().getClassMetadata(
entityClass).getPropertyNames();
for
(StringdefProperty:defPropertys){
int
ii
=
0
;
for
(ii
=
0
;ii
<
propertyNames.length;
++
ii){
if
(defProperty.equals(propertyNames[ii])){
criteria.addOrder(Order.asc(defProperty));
break
;
}
}
if
(ii
==
propertyNames.length){
exam.excludeProperty(defProperty);
}
}
criteria.add(exam);
return
(List
<
T
>
)criteria.list();
}
//
使用指定的实体及属性检索(满足属性like串实体值)数据
public
List
<
T
>
findLikeByEntity(Tentity,String[]propertyNames){
Criteriacriteria
=
this
.createCriteria();
for
(Stringproperty:propertyNames){
try
{
Objectvalue
=
PropertyUtils.getProperty(entity,property);
if
(value
instanceof
String){
criteria.add(Restrictions.like(property,(String)value,
MatchMode.ANYWHERE));
criteria.addOrder(Order.asc(property));
}
else
{
criteria.add(Restrictions.eq(property,value));
criteria.addOrder(Order.asc(property));
}
}
catch
(Exceptionex){
//
忽略无效的检索参考数据。
}
}
return
(List
<
T
>
)criteria.list();
}
//
使用指定的检索标准获取满足标准的记录数
public
IntegergetRowCount(DetachedCriteriacriteria){
criteria.setProjection(Projections.rowCount());
Listlist
=
this
.findByCriteria(criteria,
0
,
1
);
return
(Integer)list.get(
0
);
}
//
使用指定的检索标准检索数据,返回指定统计值(max,min,avg,sum)
public
ObjectgetStatValue(DetachedCriteriacriteria,StringpropertyName,
StringStatName){
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
;
Listlist
=
this
.findByCriteria(criteria,
0
,
1
);
return
list.get(
0
);
}
//
--------------------------------Others--------------------------------
//
加锁指定的实体
public
void
lock(Tentity,LockModelock){
getHibernateTemplate().lock(entity,lock);
}
//
强制初始化指定的实体
public
void
initialize(Objectproxy){
getHibernateTemplate().initialize(proxy);
}
//
强制立即更新缓冲数据到数据库(否则仅在事务提交时才更新)
public
void
flush(){
getHibernateTemplate().flush();
}
}
//以上代码来自网上收集
以上就实现了泛型的 Hibernate Dao 了,下面的例子就是业务对象对 GenericHibernateDao的使用
业务对象 Article 对应文章表的 aticle 表
package
com.th.huz.model;
import
java.io.Serializable;
import
java.util.Date;
public
class
Article
implements
Serializable{
private
static
final
long
serialVersionUID
=
1072812006693587010L
;
private
long
id;
private
Stringtitle;
private
Stringauthor;
private
DatepubDate;
private
Stringcontent;
public
long
getId(){
return
id;
}
public
void
setId(
long
id){
this
.id
=
id;
}
public
StringgetTitle(){
return
title;
}
public
void
setTitle(Stringtitle){
this
.title
=
title;
}
public
StringgetAuthor(){
return
author;
}
public
void
setAuthor(Stringauthor){
this
.author
=
author;
}
public
DategetPubDate(){
return
pubDate;
}
public
void
setPubDate(DatepubDate){
this
.pubDate
=
pubDate;
}
public
StringgetContent(){
return
content;
}
public
void
setContent(Stringcontent){
this
.content
=
content;
}
}
定义 Article 业务对象的Dao 接口 IArticleDao ,它继承自 GenericDao 接口,以获得其中的方法
你可以在 IArticleDao 中添加 Article 业务对象特有的方法,也可以直接使用 GenericDao 中提供的所有方法IArticleDao接口指定业务对象的类型和主键的类型 <Article,Long>
package
com.th.huz.model;
import
com.th.huz.dao.GenericDao;
import
com.th.huz.model.Article;
public
interface
IArticleDAO
extends
GenericDao
<
Article,Long
>
{
//
publicvoidfindById(Longid);
}
然后就可以定义 ArticleHibernateDao 类了,它只要实现 IArticleDao 接口并继承 GenericHibernateDao 类就可以使用所有的 Generic接口和IArticleDao 接口中的定义的方法。如果你在 IArticleDao 接口里指定了Article业务对象特有的方法,就在ArticleHibernateDao实现这些方法。而Generic接口中的方法,在ArticleHibernateDao 的父类 GenericHibernateDao 中已经全部实现了,直接调用就可以方便的访问数据库。
package
com.th.huz.model;
import
com.th.huz.dao.GenericHibernateDao;
public
class
ArticleHibernateDao
extends
GenericHibernateDao
<
Article,Long
>
implements
IArticleDAO{
}
其他的业务对象也可以参照 Article 和ArticleHibernateDao 类来定义, GenericDao 接口中有的通用方法就直接调用,不足的以后补充,其他业务对象特有的方法就在其他业务对象的 Dao接口(继承GenericDao接口) 中定义并通过 GenericHibernateDao 子类来实现。节省很多重复代码,简单几步就可以使用GenericDao接口的实现类GenericHibernateDao 方便地访问数据库。
最后提供一个Article 业务对象的 Hibernate 映射文件 和 建表SQL脚本 和一个 ArticleHibernateDao 类的测试类
Article的映射文件
<?
xmlversion="1.0"
?>
<!
DOCTYPEhibernate-mappingPUBLIC"-//Hibernate/HibernateMappingDTD3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
>
<!--
Article.hbm.xml
-->
<
hibernate-mapping
>
<
class
name
="com.th.huz.model.Article"
table
="article"
>
<
id
name
="id"
type
="java.lang.Long"
>
<
column
name
="id"
/>
<
generator
class
="native"
/>
</
id
>
<
property
name
="title"
type
="java.lang.String"
>
<
column
name
="title"
length
="100"
/>
</
property
>
<
property
name
="author"
>
<
column
name
="author"
length
="32"
/>
</
property
>
<
property
name
="pubDate"
type
="java.util.Date"
>
<
column
name
="pubDate"
/>
</
property
>
<
property
name
="content"
type
="java.lang.String"
>
<
column
name
="content"
/>
</
property
>
</
class
>
</
hibernate-mapping
>
Article对应的article表的建表脚本
if
exists<span style=
分享到:
评论