详细介绍 Hibernate 泛型 DAO 及其使用方法

编写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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值