通用Hibernate-Dao

在作管理系統時。一般基於Facade模式的系統持久化層要寫許多Dao。這些dao裏面的方法又是重複的,那麼有沒有什麼好的方法來統一利用一個公共的Dao。 

答案是能夠的。這裏咱們接觸到JDK5.0裏面的一個新特性:泛型。 

關於泛型的含義我這裏就再也不解釋了。 

下面咱們以一個對用戶管理和新聞管理的來示範。 

首先是2個POJO。我這裏只列出User  POJO。 
(基於註釋的Pojo)java

package com.oa;  
  
import javax.persistence.Column;  
import javax.persistence.Entity;  
import javax.persistence.GeneratedValue;  
import javax.persistence.GenerationType;  
import javax.persistence.Id;  
import javax.persistence.Table;  
  
@Entity  
@Table(name = "tb_user")  
public class User {  
  
    @Id  
    @GeneratedValue(strategy = GenerationType.IDENTITY)  
    private int id;  
  
    @Column(name = "username", length = 15)  
    private String username;  
  
    @Column(name = "password", length = 15)  
    private String password;  
  
    public int getId() {  
        return id;  
    }  
  
    public void setId(int id) {  
        this.id = id;  
    }  
  
    public String getUsername() {  
        return username;  
    }  
  
    public void setUsername(String username) {  
        this.username = username;  
    }  
  
    public String getPassword() {  
        return password;  
    }  
  
    public void setPassword(String password) {  
        this.password = password;  
    }  
  
}  
  
 

若是按照常規的Facade模式來設計,咱們的思路是: 
先建立一個UserDao的接口。 spring

package com.oa.dao;  
  
import java.util.List;  
  
import com.oa.User;  
  
public interface UserDao {  
    public void save(User user);  
  
    public void delete(int id);  
  
    public void update(User user);  
  
    public List<User> query();  
  
    public User get(int id);  
  
}  
  

而後實現這個接口:UserDaoImpl sql

package com.oa.dao.impl;  
  
import java.util.List;  
  
import org.springframework.context.annotation.Scope;  
import org.springframework.stereotype.Repository;  
  
import com.oa.User;  
import com.oa.dao.MyHibernateDaoSupport;  
import com.oa.dao.UserDao;  
  
  
  
/** 
 * 從Spring 2.0開始,引入了@Repository註解, 
 *  用它來標記充當儲存庫(又稱 Data Access Object或DAO)角色或典型的類 
 */  
  
  
/** 
 * Spring 2.5引入了更多典型化註解(stereotype annotations): @Component、@Service和 @Controller。  
 * @Component是全部受Spring管理組件的通用形式; 而@Repository、@Service和 @Controller則是@Component的細化,  
 *                   用來表示更具體的用例(例如,分別對應了持久化層、 服務層  和   表現層)。 
 */  
//@Scope("singlton")  
@Repository("userDao")//聲明此類爲數據持久層的類  
public class UserDaoImpl extends MyHibernateDaoSupport implements UserDao {  
  
    public void delete(int id) {  
        super.getHibernateTemplate().delete(  
                super.getHibernateTemplate().load(User.class, id));  
  
    }  
  
    public User get(int id) {  
  
        return (User) super.getHibernateTemplate().get("from  User", id);  
    }  
  
    @SuppressWarnings("unchecked")  
    public List<User> query() {  
        return super.getHibernateTemplate().find("from User");  
  
    }  
  
    public void save(User user) {  
        super.getHibernateTemplate().save(user);  
  
    }  
  
    public void update(User user) {  
        super.getHibernateTemplate().update(user);  
  
    }  
  
}  

持久化層完畢。 


接下來的是事務層 


先建立一個UserService的接口設計模式

package com.oa.service;  
  
import com.oa.User;  
  
public interface UserService {  
      
    public void save(User user);  
  
    public void update(User user);  
  
}  

而後實現這個接口:UserServiceImpl。 
在UserServiceImpl裏引用UserDao來實現業務邏輯。 數組

package com.oa.service.impl;  
  
import com.oa.User;  
import com.oa.service.UserService;  
import com.oa.dao.UserDao;  
  
  
import java.util.List;  
  
import org.springframework.beans.factory.annotation.Autowired;  
import org.springframework.stereotype.Service;  
  
  
  
/** 
 * 聲明此類爲業務邏輯層的類 
 * 默認bean名稱生成器會返回小寫開頭的非限定(non-qualified)類名 
 * @Service 
 * userServiceImpl 
 */  
@Service("userService")  
public class UserServiceImpl implements UserService {  
  
      
    /** 
     * @Autowired 
     *  
     * @Autowired 註解能夠用於"傳統的"setter 方法,以下例: 
     * public void setUserDao(UserDAO userDao) 
    { 
        this.userDao = userDao; 
    } 
     */  
      
    /** 
     * @Resource有一個'name'屬性,缺省時,Spring 將這個值解釋爲要注射的 bean 的名字。 
     *   @Resource(name="userDao")  
     */  
    @Autowired //  or  @Resource(name="userDao")  
    private UserDao userDao;  
  
    public void save(User user) {  
        userDao.save(user);  
  
    }  
  
    public void update(User user) {  
        userDao.update(user);  
  
    }  
  
}  
  
   

按照上面的模式:新聞管理也這麼寫一遍。 

重複的工做使得咱們以爲好煩。 


這個時候是泛型出場的時候了。 

基於Facade的設計模式,dao和service仍是要的。 這裏咱們就要設計一個公共的Dao..  咱們稱之爲:GenericDao session

package com.oa.dao;  
  
import java.io.Serializable;  
import java.util.*;  
  
/** 
 * * 
 *  
 * @param <T> 
 *            泛型,指實體類  type 
 * @param <PK> 
 *            泛型,指實體類主鍵的數據類型,如Integer,Long 
 */  
public interface GenericDao<T, PK> {  
      
    /**   
     * 保存指定實體類   
     *    
     * @param entityobj   
     *            實體類   
     */   
    public  void save(T entity);  
      
      
      /**   
     * 刪除指定實體   
     *    
     * @param entityobj   
     *            實體類   
     */    
    public void delete(T entity);  
      
      
     /** * 
     * 刪除實體 
     * @param entityClass 實體類名 
     * @param id 實體的ID 
     */  
    public void deleteById(Class<T> entityClass,PK id);  
      
      
    /**   
    * 更新或保存指定實體   
    *    
    * @param entity 實體類   
    */   
    public void saveorupdate(T entity);  
      
      
     /** * 
     * 更新實體 
     * 可用於添加、修改、刪除操做 
     * @param hql 更新的HQL語句 
     * @param params 參數,可有項目或多項目,代替Hql中的"?"號 
     */  
    public void update(final String hql,final Object[] params);  
      
      
  
    /**   
     * 模糊查詢指定條件對象集合 <br>   
     * 用法:能夠實例化一個空的T對象,須要查詢某個字段,就set該字段的條件而後調用本方法<br>   
     * 缺點:目前測試貌似只能支持String的模糊查詢,雖然有辦法重寫,但不必,其餘用HQL<br>   
     *    
     * @param entity   
     *            條件實體   
     * @return 結合   
     */    
    public List<T> findByExample(T entity);  
      
      
    /**   
     * 獲取全部實體集合   
     *    
     * @param entityClass   
     *            實體   
     * @return 集合   
     */    
    public List<T> findAll(Class<T> entityClass);  
      
    public List<T> findAll(Class<T> entityClass,String hql,Object[] params,int start, int limit);  
    /**   
     * 查找指定PK實體類對象   
     *    
     * @param entityClass   
     *            實體Class   
     * @param id   
     *            實體PK   
     * @return 實體對象   
     */     
    public T findById(Class<T> entityClass, PK id);  
      
    /** * 
     * 按HQL條件查詢列表 
     * @param hql 查詢語句,支持鏈接查詢和多條件查詢 
     * @param params 參數數組,代替hql中的"?"號 
     * @return 結果集List 
     */  
     
    public List<T> findByHql(String hql,Object[]  params);  
      
    /**   
     * 查找指定屬性的實體集合   
     *    
     * @param entityClass   
     *            實體   
     * @param propertyName   
     *            屬性名   
     * @param value   
     *            條件   
     * @return 實體集合   
     */    
    public List<T> findByProperty(Class<T> entityClass, String propertyName,Object value);  
      
      
    /**   
     * 查詢指定HQL語句的分頁數據集合   
     *    
     * @param hsql   
     *            HQL語句   
     * @param start   
     *            開始記錄號   
     * @param limit   
     *            最大記錄號   
     * @return 分頁數據集合   
     * @throws Exception   
     *             拋出異常   
     */    
    public List<T> findByPage(Class<T> entityClass,int start,int limit) ;  
      
      
      
    /** 
     * 得到總記錄數 
     */  
    public T getTotalCount(Class<T> entityClass);  
      
    public T getPageCount(String hql,Object[] params);  
  
}  
   

看到,咱們再也不是具體的User , News 
。。而是用 T  來取代實體。 


由於我這個是基於 註解的,因此附上MyHibernateDaoSupport的代碼。 測試

package com.oa.dao;  
  
import javax.annotation.Resource;  
import org.hibernate.SessionFactory;  
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;  
  
/** 
 * 咱們之因此要改寫 
 * HibernateDaoSupport,是因我爲,咱們要爲DAO層的類注入SessionFactory這個屬性。 
 * 之後,咱們開發的DAO類,就能夠直接重用這個MyHibernateDaoSupport了。 
 * 其實,這樣作是至關於配置文件方式的代碼: 
 * <bean id="userDao" class="com.oa.dao.UserDaoImpl">  
 * <property 
 * name="sessionFactory" ref="sessionFactory"/>  
 * </bean> 
 *  
 * @author Administrator 
 *  
 */  
public class MyHibernateDaoSupport extends HibernateDaoSupport {  
      
    @Resource(name="sessionFactory")    //爲父類HibernateDaoSupport注入sessionFactory的值  
    public void setSuperSessionFactory(SessionFactory sessionFactory){  
        super.setSessionFactory(sessionFactory);  
    }  
      
  
}  
  

到如今位置genericdao的接口有了,也就是咱們要作什麼。。如今就是實現它,就是怎麼作。 
GenericDaoImpl 代碼: this

package com.oa.dao.impl;  
  
import java.io.Serializable;  
import java.util.List;  
  
import org.hibernate.Query;  
import org.springframework.stereotype.Repository;  
  
import com.oa.dao.GenericDao;  
import com.oa.dao.MyHibernateDaoSupport;  
@SuppressWarnings("unchecked")  
@Repository("genericDao")   //聲明此類爲數據持久層的類  
public class GenericDaoImpl<T, PK extends Serializable> extends  
                                    MyHibernateDaoSupport implements GenericDao<T, PK> {  
  
    public void delete(T entity) {  
        super.getHibernateTemplate().delete(entity);  
    }  
  
  
    public void deleteById(Class entityClass, PK id) {  
        super.getHibernateTemplate().delete(findById(entityClass, id));  
  
    }  
      
    public void save(T entity) {  
        super.getHibernateTemplate().save(entity);  
  
    }  
  
    public void saveorupdate(T entity) {  
        super.getHibernateTemplate().saveOrUpdate(entity);  
  
    }  
  
    public void update(String hql, Object[] params) {  
             Query query = super.getSession().createQuery(hql);  
                for(int i=0; i<params.length; i++){  
                    query.setParameter(i, params[i]);  
                }  
                query.executeUpdate();  
     }  
      
  
    public List<T> findAll(Class entityClass) {  
          
        return super.getHibernateTemplate().loadAll(entityClass);  
    }  
  
    public List<T> findAll(Class entityClass, String hql, Object[] params,int start, int limit) {  
        Query query = super.getSession().createQuery(hql);  
        if(params!=null&&params.length>0){  
            for(int i = 0;i<params.length;i++){  
                query.setParameter(i, params[i]);  
            }  
        }  
        if(start!=0&&limit!=0){  
            query.setFirstResult(start).setMaxResults(limit);  
        }  
        return query.list();  
    }  
  
    public List<T> findByExample(T entity) {  
        return super.getHibernateTemplate().findByExample(entity);  
    }  
  
    public List<T> findByHql(String hql, Object[] params) {  
        Query query = super.getSession().createQuery(hql);  
        if(null!= params && params.length>0){  
            for(int i = 0; i<params.length;i++){  
                query.setParameter(i, params[i]);  
            }  
        }  
        return query.list();  
    }  
  
    public T findById(Class entityClass, PK id) {  
        return (T)super.getHibernateTemplate().get(entityClass, id);  
    }  
      
    public List<T> findByProperty(Class entityClass, String propertyName,Object value) {  
        String queryString = "from "+entityClass.getName()+ " as model where model." + propertyName + "=?";     
        return super.getHibernateTemplate().find(queryString, value);  
    }  
  
  
      
    //分頁使用  
    public List<T> findByPage(Class<T> entityClass,int start,int limit) {  
          Query query=super.getSession().createQuery("select o from "+entityClass.getName()+" o");  
          query.setFirstResult(start).setMaxResults(limit);  
        return query.list();  
    }  
  
      
    public T getTotalCount(Class entityClass) {  
          
        return (T)super.getSession().createQuery("select count(o) from "+entityClass.getName()+" o").uniqueResult();  
    }  
  
    public T getPageCount(String hql, Object[] params) {  
        Query query = super.getSession().createQuery(hql);  
        if(null!= params && params.length>0){  
            for(int i = 0; i<params.length;i++){  
                query.setParameter(i, params[i]);  
            }  
        }  
        return (T)query.list();  
    }  
  
      
  
} 


至此 泛型就告一個段落。 


接下來日子就好過了。 

咱們不是有user  news   等等一系列的curd管理。 


以User爲例子; 
定義一個user的接口, 
UserDao.Java spa

package com.oa.dao;  
  
import com.oa.User;  
  
public interface UserDao extends GenericDao<User, Integer> {  
  
public   int   login(User user);  
//其餘的方法的  
}  
  
  
而後就是實現它 UserDaoImpl  
  
package com.oa.dao.impl;  
  
  
  
import com.oa.User;  
import com.oa.dao.UserDao;  
  
public class UserDaoImpl extends GenericDaoImpl<User, Integer> implements UserDao {  
  
    public  int  login(User  user){  
//登錄判斷的方法  
  
return   XX;  
};  
  
  
//其餘的方法的實現  
  
  
}  
  

持久化層就是這麼多了。 

下面進入業務邏輯層,依然是先定義一個接口。 hibernate

package com.oa.service;  
  
import com.oa.User;  
  
public interface UserService {  
      
    public void save(User user);  
  
    public void update(User user);  
  
   public  int  login(User  user);  
  
//其餘的方法  
  
}  


接下來是實現 

package com.oa.service.impl;  
  
import com.oa.User;  
import com.oa.dao. UserDao;  
import com.oa.service.TestUserService;  
  
public class UserService implements UserService {  
  
    private  UserDao  UserDao;  
    public void save(User user) {  
        UserDao.save(user);  
  
    }  
  
    public void updasaveorupdatete(User user) {  
        UserDao.saveorupdate(user);  
  
    }  
  
    public int   login(User user) {  
        return   UserDao.login(user);  
  
    }  
  
//其餘的方法。。。。  
  
}  

Ok。。到如今咱們就利用泛型dao來設計就完畢了 二者相對比,發現dao層的代碼能夠複用,少了很多。 對於大型管理系統,效果更明顯。 

相關文章
相關標籤/搜索