Spring+Hibernate DAO 持久層開發, Spring 用 Hibernate 訪問數據庫的三種方法.推薦使用回調

DAO開發

注:
(1)以下兩者都需在Spring XML配置文件中,註冊Bean(實現類)來依賴注入SessionFactory.
(2.1)Spring 中進行事務管理的通常方式是利用AOP(面向切片編程)的方式,爲普通java類封裝事務控制,它是通過動態代理實現的,由於接口是
        延遲實例化的, spring在這段時間內通過攔截器,加載事務切片。原理就是這樣,具體細節請參考jdk中有關動態代理的文檔。本文主要講解
        如何在spring中進行事務控制。
(2.2)動態代理的一個重要特徵是,它是針對接口的,所以我們的DAO要通過動態代理來讓spring接管事務,就必須在DAO前面抽象出一個接口. 當然
       如果沒有這樣的接口,那麼spring會使用CGLIB來解決問題,但這不是spring推薦的方式.

(一)直接使用Hibernate API (不推薦使用)
public class DaoImp implate Dao{
          private SessionFactory sessionFactory;
         private static String hql = "from User u where u.username=? ";

          public void setSessionFactory(SessionFactory sessionFactory){
                     this.sessionFactory=sessionFactory;
          }

            public boolean isValidUser(String username) {
                try{
                     List userList = sessionFactory.getCurrentSession().creatQuery(hql).setParameter(0,username).list();
                      if (userList.size() > 0) {
                     return true;
                  } catch (HibernateException ex){
                      throw converHibernaterAccessException(ex);
                   }   
              }
}

優點:與Spring框架完全分離
缺點:(1)無法使用Spring框架封裝所提供的額外功能.如,直接使用Hibernate API 需用try...catch()處理HibernateException異常.
         (2)需在實現類中加入setSessionFactory(SessionFactory sessionFactory)屬性,接收依賴注入的SessionFactory.

(二)繼承 Spring 的 HibernateDaoSupport 使用 HibernateTemplate (不推薦使用getSession())
public class DaoImp extend HibernateDaoSupport implates Dao{
          //private SessionFactory sessionFactory;
         private static String hql = "from User u where u.username=? ";

          //public void setSessionFactory(SessionFactory sessionFactory){
          //           this.sessionFactory=sessionFactory;
          //}


            public boolean isValidUser(String username) {
               // try{
               //     List userList = sessionFactory.getCurrentSession().creatQuery(hql).setParameter(0,username).list();

                     List userList = getHibernateTemplate().find(hql,username);
                      if (userList.size() > 0) {
                     return true;
                // } catch (HibernateException ex){
               //      throw converHibernaterAccessException(ex);
              //   }  

              }

            public boolean isValidUser(String username,String password) throw DataAccessException {
                     Session session = getSession();                  //不推薦使用,用完後需手動關閉
                     String[] userlist=new String[2];
                      userlist[0]=username;
                     userlist[1]=password;
                  try{
                     List userList = session.find(hql,userlist);       //Hibernate語句;
                     session.close();
                      if (userList.size() > 0) {
                     return true;
                 } catch (HibernateException ex){
                      throw converHibernaterAccessException(ex);
                   }   
              }
}

特點:對HibernateTemplate沒有提供的功能,可以直接調用HibernateDaoSuppor對象的getSession()方法(極其不推薦使用)得到Session對象實例用try{ Hibernate API }catch (HibernateException ex )操作.

(三)對 HibernateTemplate 沒有提供的功能, 還可以用HibernateCallback 回調的方法管理數據庫. (極其推薦)

/**
* 使用 hql 語句進行操作
* @param hql       HSQL 查詢語句
* @param offset   開始取數據的下標
* @param length    讀取數據記錄數
* @return List        結果集
*/
public List getListForPage ( final String hql , final int offset , final int length ) {

     List list = getHibernateTemplate().executeFind ( new HibernateCallback ( ) {
            public Object doInHibernate ( Session session ) throws HibernateException, SQLException {
                     Query query = session.createQuery ( hql ) ;
                     query.setFirstResult ( offset ) ;
                     query.setMaxResults ( length ) ;
                     List list = query.list ( ) ;
                     return list ;
           }
    }) ;
    return list ;
}

 

 

 

spring+hibernate架構中Dao訪問數據庫的幾種方法
在spring+hibernate的架構中,訪問數據庫有幾種方法,按spring依賴注入來區分有3種,在這之前先再來了解一下spring的依賴注入,spring主要的兩大核心就是IOC(控制反轉)和AOP(面向切面編程),控制反轉就是控制轉移,從以往由Bean去控制要調用的接口或其他資源轉移給容器,由容器來尋找並實例化要調用的接口,也可以解釋成依賴注入,即在spring配置文件中把要調用的接口、設置、構造子配置給Bean。這邊是以依賴注入來區分爲sessionFactory、hibernateTemplate、jdbcTemplate,本質上劃分只有hibernateTemplate和jdbcTemplate這兩種。1、注入sessionFactory
在spring配置文件中,對Dao注入sessionFactory,即:
<bean id="classDao" class="cn.jmu.data.dao.impl.ClassImpl">
<property name="sessionFactory">
   <ref local="sessionFactory" />
</property>
</bean>
這邊sessionFactory依賴注入的不是給Dao層中的類,而是給HibernateDaoSupport,見spring源文件org/springframework/orm/hibernate3/support/HibernateDaoSupport.java裏面,就有sessionFactory的set、get操作:public final void setSessionFactory(SessionFactory sessionFactory) {
   this.hibernateTemplate = createHibernateTemplate(sessionFactory);//通過sessionFactory來生成hibernateTemplate
}public final SessionFactory getSessionFactory() {
   return (this.hibernateTemplate != null ? this.hibernateTemplate.getSessionFactory() : null);
}所以在Dao層中類繼承HibernateDaoSupport,即可通過this.getHibernateTemplate()來對數據庫進行操作,
   更新數據:this.getHibernateTemplate().update(bo);
   查詢數據:this.getHibernateTemplate().find(bo);
   添加數據:this.getHibernateTemplate().save(bo) ;
   刪除數據:this.getHibernateTemplate().delete(bo);
從上面可以看出spring+hibernate的強大威力,存取數據不用像以往jdbc那樣,要寫一大串try,catch語句,還要連接數據庫,用完再關閉數據庫連接,而用一條語句就可以搞定。
這裏sessionFactory由spring自動自動連接、關閉,當然你也可以手動來連接、關閉,如下面採用的方法:
Session session=this.getHibernateTemplate().getSessionFactory().openSession();
Transaction tx=session.beginTransaction();
/*--------------查詢數據------------------------*/
String str="hql";
Query query=session.createQuery(str);
List list=query.list();
/*--------------刪除數據------------------------*/
session.load(bo,ID);
   session.delete(bo);
/*--------------添加數據------------------------*/
session.save(bo);  
/*--------------修改數據-----------------------*/
session.load(bo,ID);
   session.update(bo);
/*--------------end---------------------------*/
tx.commit();
session.close();
初學Hebernate的人對這些代碼應該很熟悉,沒有spring提供hibernateTemplate,在單單的Hibernate中就得用這種方面去訪問存取數據了。
2、注入hibernateTemplate
這種方法本質跟上面注入sessionFactory一樣,只不過再進行一層包裝,這樣最大的好處就是Dao中的類就不用再繼承HibernateDaoSupport(在java中是單繼承的,這唯一一次的繼承就被HibernateDaoSupport剝奪去就豈不可惜?)不過在這之前要先要配置好hibernateTemplate,即:
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
        <property name="sessionFactory">
            <ref bean="sessionFactory"/>
        </property>
    </bean>
再對要用到hibernateTemplate的Dao進行注入依賴,即:
<bean id="ClassDao" class="cn.jmu.data.dao.impl.ClassImpl">
<property name="hibernateTemplate">
   <ref bean="hibernateTemplate"/>
</property>
</bean>
在Dao層的類就要添加hibernateTemplate對象,來對應配置文件中所注入的依賴:
private HibernateTemplate hibernateTemplate;
public HibernateTemplate getHibernateTemplate() {
return hibernateTemplate;
}
public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
this.hibernateTemplate = hibernateTemplate;
}
hibernateTemplate對數據的增刪查給就跟上面的一樣,即:
   更新數據:hibernateTemplate().update(bo);
   查詢數據:hibernateTemplate().find(bo);
   添加數據:hibernateTemplate().save(bo) ;
   刪除數據:hibernateTemplate().delete(bo);
3、注入jdbcTemplate如果對以前的jdbc的SQL還念念不忘,又對Hibernate的HQL沒有好感的話,就可以採用jdbcTemplate來增刪查改數據庫了。在某些情況下采用jdbcTemplate還比較方便,甚至還能提高查詢效率。在這之前也要像注入hibernateTemplate那樣,先配置好jdbcTemplate,<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
   <property name="dataSource">
    <ref bean="dataSource" />
   </property>
</bean>如果jdbcTemplate和hibernateTemplate配置時都指向同一個dataSource,那就可以共用同一個事務了。再對要用到jdbcTemplate的Dao進行注入依賴,即:<bean id="classDao" class="cn.jmu.data.dao.impl.ClassImpl">
   <property name="jdbctemplate">
    <ref bean="jdbcTemplate" />
   </property>
</bean>在Dao層的類就要添加jdbctemplate對象,來對應配置文件中所注入的依賴:protected JdbcTemplate jdbctemplate;public JdbcTemplate getJdbctemplate() {
   return jdbctemplate;
}public void setJdbctemplate(JdbcTemplate jdbctemplate) {
   this.jdbctemplate = jdbctemplate;
}現在就可以通過jdbctemplate存取數據了:查詢數據:
/*------------查詢單列-------------------*/
String SQL= "select name from table";
    List   list= jdbctemplate.queryForList(SQL);
/*------------查詢多列------------------*/
Hashtable hash = new Hashtable();
jdbctemplate.query(SQL,
     new RowCallbackHandler() {
       public void processRow(ResultSet rs) throws SQLException {
            hash.put(rs.getString(1),rs.getString(2));
      }
   });
/*----------查詢後填充到vo裏面-----------*/
String SQL="select * from table where id=?";
String[] obj = new String[1];
   obj[0] = N;
VO vo= new VO();            //這邊暫用VO來表示,VO的本質不是這樣的
List list = jdbcTemplate.query(SQL,obj,vo);
VO要實現RowMapper接口中的mapRow方法,把結果集填充到bo裏面:class VO implements RowMapper{
public Object mapRow(ResultSet rs, int index) throws SQLException {
    Bo bo = new Bo();     
   bo.setProperty(rs.getString(1));
     bo.setProperty(rs.getString(2));
     bo.setProperty(rs.getString(3));
     return bo;
    }
}/*----------------更新數據------------------*/
String SQL="update table set name=?";
String[] obj=new String[1];
obj[1]="new name";
jdbcTemplate.update(SQL,obj);
/*----------------刪除數據------------------*/
String SQL="delete from table where id='"+ID+"'";
jdbcTemplate.execute(SQL);
/*----------------添加數據------------------*/
String SQL="insert into table (property1,property2) values ('"+property1+"','"+property1+"')";
jdbcTemplate.execute(SQL);

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章