Hibernate也須要呵護——Hibernate的泛型DAO


        眾所周之。面向對象的基礎是抽象。也能夠說,抽象促使編程在不斷發展。

對於數據庫的訪問,以前寫過HqlHelper。EFHelper。編寫Spring+Hibernate框架下的應用。也相同離不了編寫一個通用的泛型GenericHibernateDao。查閱了網上不少的GenericHibernateDao實現,歸納整理為例如以下實現,供興許編碼參考。


一、 DAO泛型的接口 GenericDao

package ICT.framework.orm.hibernate;

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  lianhai

 */
public interface GenericDao<T extends Serializable, PK extends Serializable> {
    // -------------------- 基本檢索、添加、改動、刪除操作 --------------------

    // 依據主鍵獲取實體。

假設沒有對應的實體。返回 null。

public T get(PK id); // 依據主鍵獲取實體並加鎖。假設沒有對應的實體。返回 null。 public T getWithLock(PK id, LockMode lock); // 依據主鍵獲取實體。

假設沒有對應的實體。拋出異常。 public T load(PK id); // 依據主鍵獲取實體並加鎖。假設沒有對應的實體,拋出異常。

public T loadWithLock(PK id, LockMode lock); // 獲取所有實體。 public List<T> loadAll(); // loadAllWithLock() ? // 更新實體 public void update(T entity); // 更新實體並加鎖 public void updateWithLock(T entity, LockMode lock); // 存儲實體到數據庫 public void save(T entity); // saveWithLock() // 添加或更新實體 public void saveOrUpdate(T entity); // 添加或更新集合中的所有實體 public void saveOrUpdateAll(Collection<T> entities); // 刪除指定的實體 public void delete(T entity); // 加鎖並刪除指定的實體 public void deleteWithLock(T entity, LockMode lock); // 依據主鍵刪除指定實體 public void deleteByKey(PK id); // 依據主鍵加鎖並刪除指定的實體 public void deleteByKeyWithLock(PK id, LockMode lock); // 刪除集合中的所有實體 public void deleteAll(Collection<T> entities); // -------------------- HQL ---------------------------------------------- // 使用HQL語句直接添加、更新、刪除實體 public int bulkUpdate(String queryString); // 使用帶參數的HQL語句添加、更新、刪除實體 public int bulkUpdate(String queryString, Object[] values); // 使用HQL語句檢索數據 public List find(String queryString); // 使用帶參數的HQL語句檢索數據 public List find(String queryString, Object[] values); // 使用帶命名的參數的HQL語句檢索數據 public List findByNamedParam(String queryString, String[] paramNames,Object[] values); // 使用命名的HQL語句檢索數據 public List findByNamedQuery(String queryName); // 使用帶參數的命名HQL語句檢索數據 public List findByNamedQuery(String queryName, Object[] values); // 使用帶命名參數的命名HQL語句檢索數據 public List findByNamedQueryAndNamedParam(String queryName, String[] paramNames, Object[] values); // 使用HQL語句檢索數據,返回 Iterator public Iterator iterate(String queryString); // 使用帶參數HQL語句檢索數據,返回 Iterator public Iterator iterate(String queryString, Object[] values); // 關閉檢索返回的 Iterator public void closeIterator(Iterator it); // -------------------------------- Criteria ------------------------------ // 創建與會話無關的檢索標准對象 public DetachedCriteria createDetachedCriteria(); // 創建與會話綁定的檢索標准對象 public Criteria createCriteria(); // 使用指定的檢索標准檢索數據 public List findByCriteria(DetachedCriteria criteria); // 使用指定的檢索標准檢索數據。返回部分記錄 public List findByCriteria(DetachedCriteria criteria, int firstResult, int maxResults); // 使用指定的實體及屬性檢索(滿足除主鍵外屬性=實體值)數據 public List<T> findEqualByEntity(T entity, String[] propertyNames); // 使用指定的實體及屬性(非主鍵)檢索(滿足屬性 like 串實體值)數據 public List<T> findLikeByEntity(T entity, String[] propertyNames); // 使用指定的檢索標准檢索數據。返回指定范圍的記錄 public Integer getRowCount(DetachedCriteria criteria); // 使用指定的檢索標准檢索數據,返回指定統計值 public Object getStatValue(DetachedCriteria criteria, String propertyName, String StatName); // -------------------------------- Others -------------------------------- // 加鎖指定的實體 public void lock(T entity, LockMode lockMode); // 強制初始化指定的實體 public void initialize(Object proxy); // 強制馬上更新緩沖數據到數據庫(否則僅在事務提交時才更新) public void flush(); }


二、 GenericDao接口的實現類 GenericHibernateDao

package ICT.framework.orm.hibernate.impl;

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 各項功能,
 * 簡化基於Hibernate Dao 的編寫。

* * @author lianhai */ @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; Class c = getClass(); Type t = c.getGenericSuperclass(); if (t instanceof ParameterizedType) { Type[] p = ((ParameterizedType) t).getActualTypeArguments(); this.entityClass = (Class<T>) p[0]; } } // -------------------- 基本檢索、添加、改動、刪除操作 -------------------- // 依據主鍵獲取實體。

假設沒有對應的實體。返回 null。

public T get(PK id) { return (T) getHibernateTemplate().get(entityClass, id); } // 依據主鍵獲取實體並加鎖。

假設沒有對應的實體,返回 null。 public T getWithLock(PK id, LockMode lock) { T t = (T) getHibernateTemplate().get(entityClass, id, lock); if (t != null) { this.flush(); // 馬上刷新,否則鎖不會生效。 } return t; } // 依據主鍵獲取實體。

假設沒有對應的實體,拋出異常。

public T load(PK id) { return (T) getHibernateTemplate().load(entityClass, id); } // 依據主鍵獲取實體並加鎖。假設沒有對應的實體,拋出異常。 public T loadWithLock(PK id, LockMode lock) { T t = (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(T entity) { getHibernateTemplate().update(entity); } // 更新實體並加鎖 public void updateWithLock(T entity, LockMode lock) { getHibernateTemplate().update(entity, lock); this.flush(); // 馬上刷新,否則鎖不會生效。 } // 存儲實體到數據庫 public void save(T entity) { getHibernateTemplate().save(entity); } // saveWithLock()? // 添加或更新實體 public void saveOrUpdate(T entity) { getHibernateTemplate().saveOrUpdate(entity); } // 添加或更新集合中的所有實體 public void saveOrUpdateAll(Collection<T> entities) { getHibernateTemplate().saveOrUpdateAll(entities); } // 刪除指定的實體 public void delete(T entity) { getHibernateTemplate().delete(entity); } // 加鎖並刪除指定的實體 public void deleteWithLock(T entity, LockMode lock) { getHibernateTemplate().delete(entity, lock); this.flush(); // 馬上刷新,否則鎖不會生效。

} // 依據主鍵刪除指定實體 public void deleteByKey(PK id) { this.delete(this.load(id)); } // 依據主鍵加鎖並刪除指定的實體 public void deleteByKeyWithLock(PK id, LockMode lock) { this.deleteWithLock(this.load(id), lock); } // 刪除集合中的所有實體 public void deleteAll(Collection<T> entities) { getHibernateTemplate().deleteAll(entities); } // -------------------- HQL ---------------------------------------------- // 使用HSQL語句直接添加、更新、刪除實體 public int bulkUpdate(String queryString) { return getHibernateTemplate().bulkUpdate(queryString); } // 使用帶參數的HQL語句添加、更新、刪除實體 public int bulkUpdate(String queryString, Object[] values) { return getHibernateTemplate().bulkUpdate(queryString, values); } // 使用HQL語句檢索數據 public List find(String queryString) { return getHibernateTemplate().find(queryString); } // 使用帶參數的HQL語句檢索數據 public List find(String queryString, Object[] values) { return getHibernateTemplate().find(queryString, values); } // 使用帶命名的參數的HQL語句檢索數據 public List findByNamedParam(String queryString, String[] paramNames, Object[] values) { return getHibernateTemplate().findByNamedParam(queryString, paramNames,values); } // 使用命名的HSQL語句檢索數據 public List findByNamedQuery(String queryName) { return getHibernateTemplate().findByNamedQuery(queryName); } // 使用帶參數的命名HQL語句檢索數據 public List findByNamedQuery(String queryName, Object[] values) { return getHibernateTemplate().findByNamedQuery(queryName, values); } // 使用帶命名參數的命名HQL語句檢索數據 public List findByNamedQueryAndNamedParam(String queryName, String[] paramNames, Object[] values) { return getHibernateTemplate().findByNamedQueryAndNamedParam(queryName,paramNames, values); } // 使用HQL語句檢索數據,返回 Iterator public Iterator iterate(String queryString) { return getHibernateTemplate().iterate(queryString); } // 使用帶參數HQL語句檢索數據。返回 Iterator public Iterator iterate(String queryString, Object[] values) { return getHibernateTemplate().iterate(queryString, values); } // 關閉檢索返回的 Iterator public void closeIterator(Iterator it) { getHibernateTemplate().closeIterator(it); } // -------------------------------- Criteria ------------------------------ // 創建與會話無關的檢索標准 public DetachedCriteria createDetachedCriteria() { return DetachedCriteria.forClass(this.entityClass); } // 創建與會話綁定的檢索標准 public Criteria createCriteria() { return this.createDetachedCriteria().getExecutableCriteria( this.getSession()); } // 檢索滿足標准的數據 public List findByCriteria(DetachedCriteria criteria) { return getHibernateTemplate().findByCriteria(criteria); } // 檢索滿足標准的數據,返回指定范圍的記錄 public List findByCriteria(DetachedCriteria criteria, int firstResult, int maxResults) { return getHibernateTemplate().findByCriteria(criteria, firstResult, maxResults); } // 使用指定的實體及屬性檢索(滿足除主鍵外屬性=實體值)數據 public List<T> findEqualByEntity(T entity, String[] propertyNames) { Criteria criteria = this.createCriteria(); Example exam = Example.create(entity); exam.excludeZeroes(); String[] defPropertys = getSessionFactory().getClassMetadata( entityClass).getPropertyNames(); for (String defProperty : 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(T entity, String[] propertyNames) { Criteria criteria = this.createCriteria(); for (String property : propertyNames) { try { Object value = 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 (Exception ex) { // 忽略無效的檢索參考數據。

} } return (List<T>) criteria.list(); } // 使用指定的檢索標准獲取滿足標准的記錄數 public Integer getRowCount(DetachedCriteria criteria) { criteria.setProjection(Projections.rowCount()); List list = this.findByCriteria(criteria, 0, 1); return (Integer) list.get(0); } // 使用指定的檢索標准檢索數據,返回指定統計值(max,min,avg,sum) public Object getStatValue(DetachedCriteria criteria, String propertyName, String StatName) { 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); } // -------------------------------- Others -------------------------------- // 加鎖指定的實體 public void lock(T entity, LockMode lock) { getHibernateTemplate().lock(entity, lock); } // 強制初始化指定的實體 public void initialize(Object proxy) { getHibernateTemplate().initialize(proxy); } // 強制馬上更新緩沖數據到數據庫(否則僅在事務提交時才更新) public void flush() { getHibernateTemplate().flush(); } }

      以上就實現了泛型的 Hibernate Dao 了,以下的樣例就是業務對象對 GenericHibernateDao的使用

三、 業務對象 Article

public class Article implements Serializable {

    private static final long serialVersionUID = 1072812006693587010L;
    
    private long id;
    private String title;
    private String author;
    private Date pubDate;
    private String content;

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public Date getPubDate() {
        return pubDate;
    }

    public void setPubDate(Date pubDate) {
        this.pubDate = pubDate;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}


四、 業務對象Article 的Dao 接口 IArticleDao
        定義 Article 業務對象的Dao 接口 IArticleDao ,它繼承自 GenericDao 接口,以獲得當中的方法。

能夠在 IArticleDao 中加入 Article 業務對象特有的方法,也能夠直接使用 GenericDao 中提供的全部方法IArticleDao接口指定業務對象的類型和主鍵的類型 <Article,Long>

public interface IArticleDAO extends GenericDao <Article,Long> {
//    public void findById(Long id);
}

五、 ArticleHibernateDao 類

        如今就能夠定義 ArticleHibernateDao 類了,它僅僅要實現 IArticleDao 接口並繼承 GenericHibernateDao 類 就能夠使用全部的 Generic 接口和  IArticleDao 接口中的定義的方法。假設你在 IArticleDao 接口里指定了Article業務對象特有的方法,就在ArticleHibernateDao實現這些方法。而Generic 接口中的方法。在ArticleHibernateDao 的父類 GenericHibernateDao 中已經所有實現了,直接調用就能夠方便的訪問數據庫。


public class ArticleHibernateDao extends GenericHibernateDao<Article,Long> implements  IArticleDAO {

}


故:

        其它的業務對象也能夠參照 Article 和 ArticleHibernateDao 類來定義 , GenericDao 接口中有的通用方法就直接調用,不足的以后補充。其它業務對象特有的方法就 在其它業務對象的 Dao接口(繼承GenericDao接口) 中定義並通過 GenericHibernateDao  子類來實現。 節省非常多反復代碼。簡單幾步就能夠使用GenericDao接口的實現類 GenericHibernateDao 方便地訪問數據庫。


補:

最后提供一個 Article 業務對象的 Hibernate 映射文件和一個 ArticleHibernateDao 類的測試類

        Article的映射文件

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Article.hbm.xml -->
<hibernate-mapping>
    <class name="com.pplsunny.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>

         ArticleHibernateDao的測試類,僅僅提供了seve(article) 方法的測試代碼

public class ArticleHibernateDaoTest extends TestCase {

    ApplicationContext ctx = new ClassPathXmlApplicationContext(
            "applicationContext.xml");
    ArticleHibernateDao adh = (ArticleHibernateDao) ctx
            .getBean("articleHibernateDao");

    public void testSave() {
        Article art = (Article) ctx.getBean("article");
        art.setId(1);
        art.setTitle("標題1");
        art.setAuthor("作者1");
        adh.save(art);
    }
}




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM