日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

Spring3整合Hibernate3

 請(qǐng)叫我星哥 2014-09-15

6.5  Spring整合Hibernate
時(shí)至今日,可能極少有J2EE應(yīng)用會(huì)直接以JDBC方式進(jìn)行持久層訪問。畢竟,用面向?qū)ο蟮某绦蛟O(shè)計(jì)語言來訪問關(guān)系型數(shù)據(jù)庫,是一件讓人沮喪的事情。大部分時(shí)候,J2EE應(yīng)用都會(huì)以O(shè)RM框架來進(jìn)行持久層訪問,在所有的ORM框架中,Hibernate以其靈巧、輕便的封裝贏得了眾多開發(fā)者的青睞。
Spring具有良好的開放性,能與大部分ORM框架良好整合。下面將詳細(xì)介紹Spring與Hibernate的整合。
6.5.1  Spring提供的DAO支持
DAO模式是一種標(biāo)準(zhǔn)的J2EE設(shè)計(jì)模式,DAO模式的核心思想是,所有的數(shù)據(jù)庫訪  問,都通過DAO組件完成,DAO組件封裝了數(shù)據(jù)庫的增、刪、改等原子操作。而業(yè)務(wù)邏輯組件則依賴于DAO組件提供的數(shù)據(jù)庫原子操作,完成系統(tǒng)業(yè)務(wù)邏輯的實(shí)現(xiàn)。
對(duì)于J2EE應(yīng)用的架構(gòu),有非常多的選擇,但不管細(xì)節(jié)如何變換,J2EE應(yīng)用都大致可分為如下3層:
  ● 表現(xiàn)層。
  ● 業(yè)務(wù)邏輯層。
  ● 數(shù)據(jù)持久層。
輕量級(jí)J2EE架構(gòu)以Spring IoC容器為核心,承上啟下。其向上管理來自表現(xiàn)層的Action,向下管理業(yè)務(wù)邏輯層組件,同時(shí)負(fù)責(zé)管理業(yè)務(wù)邏輯層所需的DAO對(duì)象。各層之間負(fù)責(zé)傳值的是值對(duì)象,也就是JavaBean實(shí)例。
圖6.5精確地描繪了輕量級(jí)J2EE架構(gòu)的大致情形。
DAO組件是整個(gè)J2EE應(yīng)用的持久層訪問的重要組件,每個(gè)J2EE應(yīng)用的底層實(shí)現(xiàn)都難以離開DAO組件的支持。Spring對(duì)實(shí)現(xiàn)DAO組件提供了許多工具類,系統(tǒng)的DAO組件可通過繼承這些工具類完成,從而可以更加簡(jiǎn)便地實(shí)現(xiàn)DAO組件。
Spring的DAO支持,允許使用相同的方式、不同的數(shù)據(jù)訪問技術(shù),如JDBC、Hibernate或JDO。Spring的DAO在不同的持久層訪問技術(shù)上提供抽象,應(yīng)用的持久層訪問基于Spring的DAO抽象。因此,應(yīng)用程序可以在不同的持久層技術(shù)之間切換。
Spring提供了一系列的抽象類,這些抽象將被作為應(yīng)用中DAO實(shí)現(xiàn)類的父類。通過繼承這些抽象類,Spring簡(jiǎn)化了DAO的開發(fā)步驟,能以一致的方式使用數(shù)據(jù)庫訪問技術(shù)。不管底層采用JDBC、JDO或Hibernate,應(yīng)用中都可采用一致的編程模型。

 

 

應(yīng)用的DAO類繼承這些抽象類,會(huì)大大簡(jiǎn)化應(yīng)用的開發(fā)。最大的好處是,繼承這些抽象類的DAO能以一致的方式訪問數(shù)據(jù)庫,意味著應(yīng)用程序可以在不同的持久層訪問技術(shù)中切換。
除此之外,Spring提供了一致的異常抽象,將原有的Checked異常轉(zhuǎn)換包裝成Runtime異常,因而,編碼時(shí)無須捕獲各種技術(shù)中特定的異常。Spring DAO體系中的異常,都繼承DataAccessException,而DataAccessException異常是Runtime的,無須顯式捕捉。通過DataAccessException的子類包裝原始異常信息,從而保證應(yīng)用程序依然可以捕捉到原始異常信息。
Spring提供了多種數(shù)據(jù)庫訪問技術(shù)的DAO支持,包括Hibernate、JDO、TopLink、iBatis、OJB等。Spring可以使用相同的訪問模式、不同的數(shù)據(jù)庫訪問技術(shù)。就Hibernate的持久層訪問技術(shù)而言,Spring提供了如下3個(gè)工具類(或接口)來支持DAO組件的實(shí)現(xiàn):
  ● HibernateDaoSupport。
  ● HibernateTemplate。
  ● HibernateCallBack。

6.5.2  管理Hibernate的SessionFactory
前面介紹Hibernate時(shí)已經(jīng)知道,在通過Hibernate進(jìn)行持久層訪問時(shí),Hibernate的SessionFactory是一個(gè)非常重要的對(duì)象,它是單個(gè)數(shù)據(jù)庫映射關(guān)系編譯后的內(nèi)存鏡像。大部分情況下,一個(gè)J2EE應(yīng)用對(duì)應(yīng)一個(gè)數(shù)據(jù)庫,也即對(duì)應(yīng)一個(gè)SessionFactory對(duì)象。
在純粹的Hibernate訪問中,應(yīng)用程序需要手動(dòng)創(chuàng)建SessionFactory實(shí)例,可想而知,這不是一個(gè)優(yōu)秀的策略。在實(shí)際開發(fā)中,希望以一種聲明式的方式管理SessionFactory實(shí)例,直接以配置文件來管理SessionFactory實(shí)例,在示范Struts的PlugIn擴(kuò)展點(diǎn)時(shí),大致示范了這種方式(請(qǐng)參閱2.12.1節(jié)的內(nèi)容)。
Spring的IoC容器則提供了更好的管理方式,它不僅能以聲明式的方式配置Session- Factory實(shí)例,也可充分利用IoC容器的作用,為SessionFactory注入數(shù)據(jù)源引用。
下面是Spring配置文件中配置Hibernate SessionFactory的示范代碼:

Xml代碼  收藏代碼
  1. <?xml version="1.0" encoding="GBK"?>   
  2. <!-- beans是Spring配置文件的根元素,并且指定了Schema信息 -->   
  3. <beans xmlns="http://www./schema/beans"   
  4.        xmlns:xsi="http://www./2001/XMLSchema-instance"   
  5.        xsi:schemaLocation="http://www./schema/beans http://www./schema/beans/spring-beans.xsd">   
  6.     <!-- 定義數(shù)據(jù)源Bean,使用C3P0數(shù)據(jù)源實(shí)現(xiàn) -->   
  7.     <bean id="dataSource" class="com.mchange.v2.c3p0. ComboPooledDataSource"   
  8.     destroy-method="close">   
  9.         <!-- 指定連接數(shù)據(jù)庫的驅(qū)動(dòng) -->   
  10.         <property name="driverClass" value="com.mysql.jdbc.Driver"/>   
  11.         <!-- 指定連接數(shù)據(jù)庫的URL -->   
  12.         <property name="jdbcUrl" value="jdbc:mysql://localhost/j2ee"/>   
  13.         <!-- 指定連接數(shù)據(jù)庫的用戶名 -->   
  14.         <property name="user" value="root"/>   
  15.         <!-- 指定連接數(shù)據(jù)庫的密碼 -->   
  16.         <property name="password" value="32147"/>   
  17.         <!-- 指定連接數(shù)據(jù)庫連接池的最大連接數(shù) -->   
  18.         <property name="maxPoolSize" value="40"/>   
  19.         <!-- 指定連接數(shù)據(jù)庫連接池的最小連接數(shù) -->   
  20.         <property name="minPoolSize" value="1"/>   
  21.         <!-- 指定連接數(shù)據(jù)庫連接池的初始化連接數(shù) -->   
  22.         <property name="initialPoolSize" value="1"/>   
  23.         <!-- 指定連接數(shù)據(jù)庫連接池的連接最大空閑時(shí)間 -->   
  24.         <property name="maxIdleTime" value="20"/>   
  25.     </bean>   
  26.     <!-- 定義Hibernate的SessionFactory -->   
  27.     <bean id="sessionFactory" class="org.springframework.orm.hibernate3.   
  28.     LocalSessionFactoryBean">   
  29.         <!-- 依賴注入數(shù)據(jù)源,正是上文定義的dataSource -->   
  30.         <property name="dataSource" ref="dataSource"/>   
  31.         <!-- mappingResources屬性用來列出全部映射文件 -->   
  32.         <property name="mappingResources">   
  33.               <list>   
  34.                   <!-- 以下用來列出所有的PO映射文件 -->   
  35.                 <value>lee/MyTest.hbm.xml</value>   
  36.               </list>   
  37.         </property>   
  38.           <!-- 定義Hibernate的SessionFactory屬性 -->   
  39.         <property name="hibernateProperties">   
  40.              <props>   
  41.                 <!-- 指定Hibernate的連接方言 -->   
  42.                 <prop key="hibernate.dialect">org.hibernate.dialect.   
  43.                 MySQLDialect</prop>   
  44.                 <!-- 配置啟動(dòng)應(yīng)用時(shí),是否根據(jù)Hibernate映射自動(dòng)創(chuàng)建數(shù)據(jù)表 -->   
  45.                   <prop key="hibernate.hbm2ddl.auto">update</prop>   
  46.              </props>   
  47.         </property>   
  48.     </bean>   
  49. </beans>   

 一旦在Spring的IoC容器中配置了SessionFactory Bean,它將隨應(yīng)用的啟動(dòng)而加載,并可以充分利用IoC容器的功能,將SessionFactory Bean注入任何Bean,比如DAO組件。一旦DAO組件獲得了SessionFactory Bean的引用,就可以完成實(shí)際的數(shù)據(jù)庫訪問。
當(dāng)然,Spring也支持訪問容器數(shù)據(jù)源。如果需要使用容器數(shù)據(jù)源,可將數(shù)據(jù)源Bean修改成如下配置:

Xml代碼  收藏代碼
  1. <!-- 此處配置JNDI數(shù)據(jù)源 -->   
  2. <bean id="myDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">   
  3.     <property name="jndiName">   
  4.         <!-- 指定數(shù)據(jù)源的JNDI -->   
  5.         <value>java:comp/env/jdbc/myds</value>   
  6.     </property>   
  7. </bean>   

 可見,以聲明式的方式管理SessionFactory實(shí)例,可以讓應(yīng)用在不同數(shù)據(jù)源之間切換。如果應(yīng)用更換數(shù)據(jù)庫等持久層資源,只需對(duì)配置文件進(jìn)行簡(jiǎn)單修改即可。
提示:以聲明式的方式管理SessionFactory,非常類似于早期將數(shù)據(jù)庫服務(wù)的相關(guān)信息放在web.xml文件中進(jìn)行配置。這種方式是為了提供更好的適應(yīng)性,當(dāng)持久層服務(wù)需要更改時(shí),應(yīng)用代碼無須任何改變。

6.5.3  使用HibernateTemplateHibernateTemplate提供持久層訪問模板.
使用HibernateTemplate無須實(shí)現(xiàn)特定接口,它只需要提供一個(gè)SessionFactory的引用就可執(zhí)行持久化操作。SessionFactory對(duì)象既可通過構(gòu)造參數(shù)傳入,也可通過設(shè)值方式傳入。HibernateTemplate提供如下3個(gè)構(gòu)造函數(shù):
  ● HibernateTemplate()。
  ● HibernateTemplate(org.hibernate.SessionFactory sessionFactory)。
  ● HibernateTemplate(org.hibernate.SessionFactory sessionFactory, boolean allowCreate)。
第一個(gè)構(gòu)造函數(shù),構(gòu)造一個(gè)默認(rèn)的HibernateTemplate實(shí)例。因此,使用Hibernate- Template實(shí)例之前,還必須使用方法setSessionFactory(SessionFactory sessionFactory)來為HibernateTemplate傳入SessionFactory的引用。
第二個(gè)構(gòu)造函數(shù),在構(gòu)造時(shí)已經(jīng)傳入SessionFactory引用。
第三個(gè)構(gòu)造函數(shù),其boolean型參數(shù)表明,如果當(dāng)前線程已經(jīng)存在一個(gè)非事務(wù)性的Session,是否直接返回此非事務(wù)性的Session。
在Web應(yīng)用中,通常啟動(dòng)時(shí)自動(dòng)加載ApplicationContext,SessionFactory和DAO對(duì)象都處在Spring上下文管理下,因此無須在代碼中顯式設(shè)置,可采用依賴注入完成Session- Factory和DAO的解耦,依賴關(guān)系通過配置文件來設(shè)置,如下所示:

Xml代碼  收藏代碼
  1. <?xml version="1.0" encoding="GBK"?>   
  2. <!-- beans是Spring配置文件的根元素,并且指定了Schema信息 -->   
  3. <beans xmlns="http://www./schema/beans"   
  4.        xmlns:xsi="http://www./2001/XMLSchema-instance"   
  5.        xsi:schemaLocation="http://www./schema/beans http://www./schema/beans/spring-beans.xsd">   
  6.     <!-- 定義數(shù)據(jù)源Bean,使用C3P0數(shù)據(jù)源實(shí)現(xiàn) -->   
  7.     <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"   
  8.     destroy-method="close">   
  9.         <!-- 指定連接數(shù)據(jù)庫的驅(qū)動(dòng) -->   
  10.         <property name="driverClass" value="com.mysql.jdbc.Driver"/>   
  11.         <!-- 指定連接數(shù)據(jù)庫的URL -->   
  12.         <property name="jdbcUrl" value="jdbc:mysql://localhost/j2ee"/>   
  13.         <!-- 指定連接數(shù)據(jù)庫的用戶名 -->   
  14.         <property name="user" value="root"/>   
  15.         <!-- 指定連接數(shù)據(jù)庫的密碼 -->   
  16.         <property name="password" value="32147"/>   
  17.         <!-- 指定連接數(shù)據(jù)庫連接池的最大連接數(shù) -->   
  18.         <property name="maxPoolSize" value="40"/>   
  19.         <!-- 指定連接數(shù)據(jù)庫連接池的最小連接數(shù) -->   
  20.         <property name="minPoolSize" value="1"/>   
  21.         <!-- 指定連接數(shù)據(jù)庫連接池的初始化連接數(shù) -->   
  22.         <property name="initialPoolSize" value="1"/>   
  23.         <!-- 指定連接數(shù)據(jù)庫連接池的連接最大空閑時(shí)間 -->   
  24.         <property name="maxIdleTime" value="20"/>   
  25.     </bean>   
  26.     <!-- 定義Hibernate的SessionFactory Bean -->   
  27.     <bean id="sessionFactory" class="org.springframework.orm.hibernate3.   
  28.     LocalSessionFactoryBean">   
  29.         <!-- 依賴注入數(shù)據(jù)源,注入的正是上文中定義的dataSource -->   
  30.         <property name="dataSource" ref="dataSource"/>   
  31.         <!-- mappingResources屬性用來列出全部映射文件 -->   
  32.         <property name="mappingResources">   
  33.               <list>   
  34.                   <!-- 以下用來列出所有的PO映射文件 -->   
  35.                 <value>lee/Person.hbm.xml</value>   
  36.               </list>   
  37.         </property>   
  38.           <!-- 定義Hibernate的SessionFactory屬性 -->   
  39.         <property name="hibernateProperties">   
  40.              <props>   
  41.                 <!-- 指定Hibernate的連接方言 -->   
  42.                 <prop key="hibernate.dialect">org.hibernate.dialect.   
  43.                 MySQLDialect</prop>   
  44.                 <!-- 指定啟動(dòng)應(yīng)用時(shí),是否根據(jù)Hibernate映射文件創(chuàng)建數(shù)據(jù)表 -->   
  45.                   <prop key="hibernate.hbm2ddl.auto">update</prop>   
  46.              </props>   
  47.         </property>   
  48.     </bean>   
  49.     <!-- 配置Person持久化類的DAO bean -->   
  50.     <bean id="personDao" class="lee.PersonDaoImpl">   
  51.         <!-- 采用依賴注入來傳入SessionFactory的引用 -->   
  52.         <property name="sessionFactory" ref="sessionFactory"/>   
  53.     </bean>   
  54. </beans>   

 在PersonDao組件中,所有的持久化操作都通過HibernateTemplate實(shí)例完成,而HibernateTemplate操作數(shù)據(jù)庫非常簡(jiǎn)潔,大部分CRUD操作都可通過一行代碼解決問題。下面介紹如何通過HibernateTemplate進(jìn)行持久層訪問。
HibernateTemplate提供了非常多的常用方法來完成基本的操作,比如通常的增加、刪除、修改、查詢等操作,Spring 2.0更增加了對(duì)命名SQL查詢的支持,也增加了對(duì)分頁的支持。大部分情況下,使用Hibernate的常規(guī)用法,就可完成大多數(shù)DAO對(duì)象的CRUD操作。下面是HibernateTemplate的常用方法簡(jiǎn)介:
  ● void delete(Object entity),刪除指定持久化實(shí)例。
  ● deleteAll(Collection entities),刪除集合內(nèi)全部持久化類實(shí)例。
  ● find(String queryString),根據(jù)HQL查詢字符串來返回實(shí)例集合。
  ● findByNamedQuery(String queryName),根據(jù)命名查詢返回實(shí)例集合。
  ● get(Class entityClass, Serializable id),根據(jù)主鍵加載特定持久化類的實(shí)例。
  ● save(Object entity),保存新的實(shí)例。
  ● saveOrUpdate(Object entity),根據(jù)實(shí)例狀態(tài),選擇保存或者更新。
  ● update(Object entity),更新實(shí)例的狀態(tài),要求entity是持久狀態(tài)。
  ● setMaxResults(int maxResults),設(shè)置分頁的大小。
下面是一個(gè)完整DAO類的源代碼:

Java代碼  收藏代碼
  1. public class PersonDaoImpl implements PersonDao   
  2. {   
  3.     //執(zhí)行持久化操作的HibernateTemplate實(shí)例   
  4.     private HibernateTemplate ht = null;   
  5.     private SessionFactory sessionFactory;   
  6.     //該DAO組件持久化操作所需的SessionFactory對(duì)象   
  7.     public void setSessionFactory(SessionFactory sessionFactory)   
  8.     {   
  9.         this.sessionFactory = sessionFactory;   
  10.     }   
  11.     //用于根據(jù)SessionFactory實(shí)例返回HibernateTemplate實(shí)例的方法   
  12.     private  HibernateTemplate getHibernateTemplate()   
  13.     {   
  14.         if (ht == null)   
  15.         {   
  16.               ht = new HibernateTemplate(sessionFactory);   
  17.         }   
  18.         return ht;   
  19.     }   
  20.     /**  
  21.      * 加載人實(shí)例  
  22.      * @param id 需要加載的Person實(shí)例的主鍵值  
  23.      * @return 返回加載的Person實(shí)例  
  24.      */   
  25.     public Person get(int id)   
  26.     {   
  27.         return (Person)getHibernateTemplate().get(Person.class, new   
  28.         Integer(id));   
  29.     }   
  30.     /**  
  31.      * 保存人實(shí)例  
  32.      * @param person 需要保存的Person實(shí)例  
  33.      */       
  34.     public void save(Person person)   
  35.     {   
  36.         getHibernateTemplate().save(person);   
  37.     }   
  38.     /**  
  39.      * 修改Person實(shí)例  
  40.      * @param person 需要修改的Person實(shí)例  
  41.      */   
  42.     public void update(Person person)   
  43.     {   
  44.         getHibernateTemplate().update(person);   
  45.     }   
  46.     /**  
  47.      * 刪除Person實(shí)例  
  48.      * @param id 需要?jiǎng)h除的Person的id  
  49.      */   
  50.     public void delete(int id)   
  51.     {   
  52.         getHibernateTemplate().delete(getHibernateTemplate().get(Person.   
  53.         class,new Integer(id)));   
  54.     }   
  55.     /**  
  56.      * 刪除Person實(shí)例  
  57.      * @param person 需要?jiǎng)h除的Person實(shí)例  
  58.      */   
  59.      public void delete(Person person)   
  60.     {   
  61.         getHibernateTemplate().delete(person);   
  62.     }   
  63.     /**  
  64.      * 根據(jù)用戶名查找Person  
  65.      * @param name 用戶名  
  66.      * @return 用戶名對(duì)應(yīng)的全部用戶  
  67.      */   
  68.     public List findByName(String name)   
  69.     {   
  70.         return getHibernateTemplate().find("from Person p where p.name   
  71.         like ?" , name);   
  72.     }   
  73.     /**  
  74.      * 返回全部的Person實(shí)例  
  75.      * @return 全部的Person實(shí)例  
  76.      */   
  77.     public List findAllPerson()   
  78.     {   
  79.         return getHibernateTemplate().find("from Person ");   
  80.     }   
  81. }   

 通過上面實(shí)現(xiàn)DAO組件的代碼可以看出,通過HibernateTemplate進(jìn)行持久層訪問的代碼如此清晰,大部分CRUD操作一行代碼即可完成,完全無須Hibernate訪問那些繁瑣的步驟。而且,一旦DAO組件獲得了SessionFactory的引用,即可很輕易地創(chuàng)建HibernateTemplate實(shí)例。
提示:HibernateTemplate是Spring眾多模板工具類之一,Spring正是通過這種簡(jiǎn)便地封裝,完成了開發(fā)中大量需要重復(fù)執(zhí)行的工作。

6.5.4  使用HibernateCallBackHibernateTemplate還提供了一種更加靈活的方式來操作數(shù)據(jù)庫,通過這種方式可以完全使用Hibernate的操作方式。

HibernateTemplate的靈活訪問方式可通過如下兩個(gè)方法完成:
  ● Object execute(HibernateCallback action)。
  ● List execute(HibernateCallback action)。
這兩個(gè)方法都需要一個(gè)HibernateCallback的實(shí)例,HibernateCallback實(shí)例可在任何有效的Hibernate數(shù)據(jù)訪問中使用。程序開發(fā)者通過HibernateCallback,可以完全使用Hibernate靈活的方式來訪問數(shù)據(jù)庫,解決Spring封裝Hibernate后靈活性不足的缺陷。
HibernateCallback是一個(gè)接口,該接口包含一個(gè)方法doInHibernate(org.hibernate. Session session),該方法只有一個(gè)參數(shù)Session。在開發(fā)中提供HibernateCallback實(shí)現(xiàn)類時(shí),必須實(shí)現(xiàn)接口里包含的doInHibernate方法,在該方法體內(nèi)即可獲得Hibernate Session的引用,一旦獲得了Hibernate Session的引用,就可以完全以Hibernate的方式進(jìn)行數(shù)據(jù)庫訪問。
注意:doInHibernate方法內(nèi)可以訪問Session,該Session對(duì)象是綁定在該線程的Session實(shí)例。該方法內(nèi)的持久層操作,與不使用Spring時(shí)的持久層操作完全相同。這保證了對(duì)于復(fù)雜的持久層訪問,依然可以使用Hibernate的訪問方式。
下面的代碼對(duì)HibernateDaoSupport類進(jìn)行擴(kuò)展(雖然Spring 2.0的HibernateTemplate提供了一個(gè)分頁方法setMaxResults,但僅此一個(gè)方法依然不能實(shí)現(xiàn)分頁查詢),這種擴(kuò)展主要是為該類增加了3個(gè)分頁查詢的方法,分頁查詢時(shí)必須直接調(diào)用Hibernate的Session完成,因此,必須借助于HibernateCallBack的幫助。

Java代碼  收藏代碼
  1. public class YeekuHibernateDaoSupport extends HibernateDaoSupport   
  2. {   
  3.     /**  
  4.      * 使用hql 語句進(jìn)行分頁查詢操作  
  5.      * @param hql 需要查詢的hql語句  
  6.      * @param offset 第一條記錄索引  
  7.      * @param pageSize 每頁需要顯示的記錄數(shù)  
  8.      * @return 當(dāng)前頁的所有記錄  
  9.      */   
  10.     public List findByPage(final String hql,   
  11.          final int offset, final int pageSize)   
  12.     {   
  13.         //HibernateDaoSupport已經(jīng)包含了getHibernateTemplate()方法   
  14.         List list = getHibernateTemplate().executeFind(new   
  15.         HibernateCallback()   
  16.             {   
  17.                 public Object doInHibernate(Session session)   
  18.                     throws HibernateException, SQLException   
  19.                 //該方法體內(nèi)以Hibernate方法進(jìn)行持久層訪問   
  20.                 {   
  21.                     List result = session.createQuery(hql)   
  22.                                          .setFirstResult(offset)   
  23.                                          .setMaxResults(pageSize)   
  24.                                          .list();   
  25.                     return result;   
  26.                 }   
  27.             });   
  28.         return list;   
  29.     }   
  30.     /**  
  31.      * 使用hql 語句進(jìn)行分頁查詢操作  
  32.      * @param hql 需要查詢的hql語句  
  33.      * @param value 如果hql有一個(gè)參數(shù)需要傳入,value就是傳入的參數(shù)  
  34.      * @param offset 第一條記錄索引  
  35.      * @param pageSize 每頁需要顯示的記錄數(shù)  
  36.      * @return 當(dāng)前頁的所有記錄  
  37.      */   
  38.     public List findByPage(final String hql , final Object value ,   
  39.          final int offset, final int pageSize)   
  40.     {   
  41.         List list = getHibernateTemplate().executeFind(new   
  42.         HibernateCallback()   
  43.             {   
  44.                 public Object doInHibernate(Session session)   
  45.                     throws HibernateException, SQLException   
  46.                 {   
  47.                     //下面查詢的是最簡(jiǎn)單的Hiberante HQL查詢   
  48.                     List result = session.createQuery(hql)   
  49.                                          .setParameter(0, value)   
  50.                                          .setFirstResult(offset)   
  51.                                          .setMaxResults(pageSize)   
  52.                                          .list();   
  53.                     return result;   
  54.                 }   
  55.             });   
  56.         return list;   
  57.     }   
  58.     /**  
  59.      * 使用hql 語句進(jìn)行分頁查詢操作  
  60.      * @param hql 需要查詢的hql語句  
  61.      * @param values 如果hql有多個(gè)參數(shù)需要傳入,values就是傳入的參數(shù)數(shù)組  
  62.      * @param offset 第一條記錄索引  
  63.      * @param pageSize 每頁需要顯示的記錄數(shù)  
  64.      * @return 當(dāng)前頁的所有記錄  
  65.      */   
  66.     public List findByPage(final String hql, final Object[] values,   
  67.          final int offset, final int pageSize)   
  68.     {   
  69.         List list = getHibernateTemplate().executeFind(new   
  70.         HibernateCallback()   
  71.             {   
  72.                 public Object doInHibernate(Session session)   
  73.                     throws HibernateException, SQLException   
  74.                 {   
  75.                     Query query = session.createQuery(hql);   
  76.                     for (int i = 0 ; i < values.length ; i++)   
  77.                     {   
  78.                         query.setParameter( i, values);   
  79.                     }   
  80.                     List result = query.setFirstResult(offset)   
  81.                                        .setMaxResults(pageSize)   
  82.                                        .list();   
  83.                     return result;   
  84.                 }   
  85.             });   
  86.         return list;   
  87.     }   
  88. }   

 在上面的代碼實(shí)現(xiàn)中,直接使用了getHibernateTemplate()方法,這個(gè)方法由Hibernate- DaoSupport提供。而YeekuHibernateDaoSupport是HibernateDaoSupport的子類,因此,可以直接使用該方法。
當(dāng)實(shí)現(xiàn)doInHibernate(Session session)方法時(shí),完全以Hibernate的方式進(jìn)行數(shù)據(jù)庫訪問,這樣保證了Hibernate進(jìn)行數(shù)據(jù)庫訪問的靈活性。
注意:Spring提供的XxxTemplate和XxxCallBack互為補(bǔ)充,二者體現(xiàn)了Spring框架設(shè)計(jì)的用心良苦:XxxTemplate對(duì)通用操作進(jìn)行封裝,而XxxCallBack解決了封裝后靈活性不足的缺陷。

6.5.5  實(shí)現(xiàn)DAO組件為了實(shí)現(xiàn)DAO組件,Spring提供了大量的XxxDaoSupport類,這些DAO支持類對(duì)于實(shí)現(xiàn)DAO組件大有幫助,因?yàn)檫@些DAO支持類已經(jīng)完成了大量基礎(chǔ)性工作。

Spring為Hibernate的DAO提供了工具類HibernateDaoSupport。該類主要提供如下兩個(gè)方法以方便DAO的實(shí)現(xiàn):
  ● public final HibernateTemplate getHibernateTemplate()。
  ● public final void setSessionFactory(SessionFactory sessionFactory)。
其中,setSessionFactory方法可用于接收Spring的ApplicationContext的依賴注入,可接收配置在Spring的SessionFactory實(shí)例,getHibernateTemplate方法用于返回通過SessionFactory產(chǎn)生的HibernateTemplate實(shí)例,持久層訪問依然通過HibernateTemplate實(shí)例完成。
下面實(shí)現(xiàn)的DAO組件繼承了Spring提供的HibernateDaoSupport類,依然實(shí)現(xiàn)了PersonDao接口,其功能與前面提供的PersonDao實(shí)現(xiàn)類完全相同。其代碼如下:

Java代碼  收藏代碼
  1. public class PersonDaoHibernate extends HibernateDaoSupport implements PersonDao   
  2. {   
  3.     /**  
  4.      * 加載人實(shí)例  
  5.      * @param id 需要加載的Person實(shí)例的主鍵值  
  6.      * @return 返回加載的Person實(shí)例  
  7.      */   
  8.     public Person get(int id)   
  9.     {   
  10.         return (Person)getHibernateTemplate().get(Person.class, new   
  11.         Integer(id));   
  12.     }   
  13.     /**  
  14.      * 保存人實(shí)例  
  15.      * @param person 需要保存的Person實(shí)例  
  16.      */       
  17.     public void save(Person person)   
  18.     {   
  19.         getHibernateTemplate().save(person);   
  20.     }   
  21.     /**  
  22.      * 修改Person實(shí)例  
  23.      * @param person 需要修改的Person實(shí)例  
  24.      */   
  25.     public void update(Person person)   
  26.     {   
  27.         getHibernateTemplate().update(person);   
  28.     }   
  29.     /**  
  30.      * 刪除Person實(shí)例  
  31.      * @param id 需要?jiǎng)h除的Person的id  
  32.      */   
  33.     public void delete(int id)   
  34.     {   
  35.         getHibernateTemplate().delete(getHibernateTemplate().   
  36.         get(Person.class, new Integer(id)));   
  37.     }   
  38.     /**  
  39.      * 刪除Person實(shí)例  
  40.      * @param person 需要?jiǎng)h除的Person實(shí)例  
  41.      */   
  42.     public void delete(Person person)   
  43.     {   
  44.         getHibernateTemplate().delete(person);   
  45.     }   
  46.     /**  
  47.      * 根據(jù)用戶名查找Person  
  48.      * @param name 用戶名  
  49.      * @return 用戶名對(duì)應(yīng)的全部用戶  
  50.      */   
  51.     public List findByPerson(String name)   
  52.     {   
  53.         return getHibernateTemplate().find("from Person p where p.name   
  54.         like ?" , name);           
  55.     }   
  56.     /**  
  57.      * 返回全部的Person實(shí)例  
  58.      * @return 全部的Person實(shí)例  
  59.      */   
  60.     public List findAllPerson()   
  61.     {   
  62.         return getHibernateTemplate().find("from Person ");   
  63.     }   
  64. }   

 上面的代碼與前面的PersonDAOImpl對(duì)比會(huì)發(fā)現(xiàn),代碼量大大減少。事實(shí)上,DAO的實(shí)現(xiàn)依然借助于HibernateTemplate的模板訪問方式,只是HibernateDaoSupport將依賴注入SessionFactory的工作已經(jīng)完成,獲取HibernateTemplate的工作也已完成。該DAO的配置必須依賴于SessionFactory,配置文件與前面部署DAO組件的方式完全相同,此處不再贅述。
在繼承HibernateDaoSupport的DAO實(shí)現(xiàn)里,Hibernate Session的管理完全不需要打開代碼,而由Spring來管理。Spring會(huì)根據(jù)實(shí)際的操作,采用“每次事務(wù)打開一次session”的策略,自動(dòng)提高數(shù)據(jù)庫訪問的性能。

6.5.6  使用IoC容器組裝各種組件至此為止,J2EE應(yīng)用所需要的各種組件都已經(jīng)出現(xiàn)了,從MVC層的控制器組件,到業(yè)務(wù)邏輯組件,以及持久層的DAO組件,已經(jīng)全部成功實(shí)現(xiàn)。應(yīng)用程序代碼并未將這些組件耦合在一起,代碼中都是面向接口編程,因此必須利用Spring的IoC容器將他們組合在一起。

從用戶角度來看,用戶發(fā)出HTTP請(qǐng)求,當(dāng)MVC框架的控制器組件攔截到用戶請(qǐng)求時(shí),將調(diào)用系統(tǒng)的業(yè)務(wù)邏輯組件,而業(yè)務(wù)邏輯組件則調(diào)用系統(tǒng)的DAO組件,而DAO組件則依賴于SessionFactory和DataSource等底層組件實(shí)現(xiàn)數(shù)據(jù)庫訪問。
從系統(tǒng)實(shí)現(xiàn)角度來看,IoC容器先創(chuàng)建SessionFactory和DataSource等底層組件,然后將這些底層組件注入給DAO組件,提供一個(gè)完整的DAO組件,并將此DAO組件注入給業(yè)務(wù)邏輯組件,從而提供一個(gè)完整的業(yè)務(wù)邏輯組件,而業(yè)務(wù)邏輯組件又被注入給控制器組件,控制器組件負(fù)責(zé)攔截用戶請(qǐng)求,并將處理結(jié)果呈現(xiàn)給用戶——這一系列的銜接都由Spring的IoC容器提供實(shí)現(xiàn)。
下面給出關(guān)于如何在容器中配置J2EE組件的大致模板,其模板代碼如下:

Xml代碼  收藏代碼
  1. <?xml version="1.0" encoding="GBK"?>   
  2. <!-- beans是Spring配置文件的根元素,并且指定了Schema信息 -->   
  3. <beans xmlns="http://www./schema/beans"   
  4.        xmlns:xsi="http://www./2001/XMLSchema-instance"   
  5.        xsi:schemaLocation="http://www./schema/beans http://www./schema/beans/spring-beans.xsd">   
  6.     <!-- 定義數(shù)據(jù)源Bean,使用C3P0數(shù)據(jù)源實(shí)現(xiàn) -->   
  7.     <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"   
  8.     destroy-method="close">   
  9.         <!-- 指定連接數(shù)據(jù)庫的驅(qū)動(dòng) -->   
  10.         <property name="driverClass" value="com.mysql.jdbc.Driver"/>   
  11.         <!-- 指定連接數(shù)據(jù)庫的URL -->   
  12.         <property name="jdbcUrl" value="jdbc:mysql://localhost/j2ee"/>   
  13.         <!-- 指定連接數(shù)據(jù)庫的用戶名 -->   
  14.         <property name="user" value="root"/>   
  15.         <!-- 指定連接數(shù)據(jù)庫的密碼 -->   
  16.         <property name="password" value="32147"/>   
  17.         <!-- 指定連接數(shù)據(jù)庫連接池的最大連接數(shù) -->   
  18.         <property name="maxPoolSize" value="40"/>   
  19.         <!-- 指定連接數(shù)據(jù)庫連接池的最小連接數(shù) -->   
  20.         <property name="minPoolSize" value="1"/>   
  21.         <!-- 指定連接數(shù)據(jù)庫連接池的初始化連接數(shù) -->   
  22.         <property name="initialPoolSize" value="1"/>   
  23.         <!-- 指定連接數(shù)據(jù)庫連接池的連接最大空閑時(shí)間 -->   
  24.         <property name="maxIdleTime" value="20"/>   
  25.     </bean>   
  26.     <!-- 定義Hibernate的SessionFactory Bean -->   
  27.     <bean id="sessionFactory" class="org.springframework.orm.hibernate3.   
  28.     LocalSessionFactoryBean">   
  29.         <!-- 依賴注入數(shù)據(jù)源,注入的正是上文中定義的dataSource -->   
  30.         <property name="dataSource" ref="dataSource"/>   
  31.         <!-- mappingResources屬性用來列出全部映射文件 -->   
  32.         <property name="mappingResources">   
  33.               <list>   
  34.                   <!-- 以下用來列出所有的PO映射文件 -->   
  35.                 <value>lee/Person.hbm.xml</value>   
  36.                   <!-- 此處還可列出更多的PO映射文件 -->   
  37.               </list>   
  38.         </property>   
  39.           <!-- 定義Hibernate的SessionFactory屬性 -->   
  40.         <property name="hibernateProperties">   
  41.              <props>   
  42.                 <!-- 指定Hibernate的連接方言 -->   
  43.                 <prop key="hibernate.dialect">org.hibernate.dialect.   
  44.                 MySQLDialect</prop>   
  45.                 <!-- 指定啟動(dòng)應(yīng)用時(shí),是否根據(jù)Hibernate映射文件創(chuàng)建數(shù)據(jù)表 -->   
  46.                   <prop key="hibernate.hbm2ddl.auto">update</prop>   
  47.              </props>   
  48.         </property>   
  49.     </bean>   
  50.     <!-- 配置Person持久化類的DAO Bean -->   
  51.     <bean id="personDao" class="lee.PersonDaoImpl">   
  52.         <!-- 采用依賴注入來傳入SessionFactory的引用 -->   
  53.         <property name="sessionFactory" ref="sessionFactory"/>   
  54.     </bean>   
  55.     <!-- 下面能以相同的方式配置更多的持久化Bean -->   
  56.     ...   
  57.     <bean id="myService" class="lee.MyServiceImp">   
  58.         <!-- 注入業(yè)務(wù)邏輯組件所必需的DAO組件 -->   
  59.         <property name="peronDdao" ref=" personDao "/>   
  60.         <!-- 此處可采用依賴注入更多的DAO組件 -->   
  61.         ...   
  62.     </bean>   
  63.     <!-- 配置控制器Bean,設(shè)置起作用域?yàn)镽equest -->   
  64.     <bean name="/login" class="lee.LoginAction" scope="request">   
  65.         <!-- 依賴注入控制器所必需的業(yè)務(wù)邏輯組件 -->   
  66.         <property name="myService" ref=" myService "/>   
  67.     </bean>   
  68. </beans>   

 在上面的配置文件中,同時(shí)配置了控制器Bean、業(yè)務(wù)邏輯組件Bean、DAO組件Bean以及一些基礎(chǔ)資源Bean。各組件的組織被解耦到配置文件中,而不是在代碼層次的低級(jí)耦合。
當(dāng)客戶端的HTTP請(qǐng)求向/login.do發(fā)送請(qǐng)求時(shí),將被容器中的lee.LoginAction攔截,LoginAction調(diào)用myService Bean,myService Bean則調(diào)用personDao等系列DAO組件,整個(gè)流程將系統(tǒng)中的各組件有機(jī)地組織在一起。
注意:在實(shí)際應(yīng)用中,很少會(huì)將DAO組件、業(yè)務(wù)邏輯組件以及控制組件都配置在同一個(gè)文件中。而是在不同配置文件中,配置相同一組J2EE應(yīng)用組件。

6.5.7  使用聲明式事務(wù)在上面的配置文件中,部署了控制器組件、業(yè)務(wù)邏輯組件、DAO組件,幾乎可以形成一個(gè)完整的J2EE應(yīng)用。

但有一個(gè)小小的問題:事務(wù)控制。系統(tǒng)沒有任何事務(wù)邏輯,沒有事務(wù)邏輯的應(yīng)用是不可想象的。
Spring提供了非常簡(jiǎn)潔的聲明式事務(wù)控制,只需要在配置文件中增加事務(wù)控制片段,業(yè)務(wù)邏輯代碼無須任何改變。Spring的聲明式事務(wù)邏輯,甚至支持在不同事務(wù)策略之間切換。
配置Spring聲明式事務(wù)時(shí),通常推薦使用BeanNameAutoProxyCreator自動(dòng)創(chuàng)建事務(wù)代理。通過這種自動(dòng)事務(wù)代理的配置策略,增加業(yè)務(wù)邏輯組件,只需要在BeanNameAutoProxyCreator Bean配置中增加一行即可,從而避免了增量式配置。
在上面的配置模板文件中增加如下配置片段,系統(tǒng)的myService業(yè)務(wù)邏輯組件將變成事務(wù)代理Bean,從而為業(yè)務(wù)邏輯方法增加事務(wù)邏輯。 
   

Xml代碼  收藏代碼
  1. <!-- 配置Hibernate的局部事務(wù)管理器 -->   
  2.     <!-- 使用HibernateTransactionManager類,該類是PlatformTransactionManager   
  3.     接口,針對(duì)采用Hibernate持久化連接的特定實(shí)現(xiàn) -->   
  4.     <bean id="transactionManager"   
  5.          class="org.springframework.orm.hibernate3.   
  6.          HibernateTransactionManager">   
  7.         <!-- HibernateTransactionManager  Bean需要依賴注入一個(gè)SessionFactory   
  8.         bean的引用 -->   
  9.          <property name="sessionFactory" ref="sessionFactory"/>   
  10.     </bean>   
  11.     <!-- 配置事務(wù)攔截器Bean -->   
  12.     <bean id="transactionInterceptor"   
  13.         class="org.springframework.transaction.interceptor.   
  14.         TransactionInterceptor">   
  15.         <!-- 事務(wù)攔截器bean需要依賴注入一個(gè)事務(wù)管理器 -->   
  16.         <property name="transactionManager" ref="transactionManager"/>   
  17.         <property name="transactionAttributes">   
  18.             <!-- 下面定義事務(wù)傳播屬性 -->   
  19.             <props>   
  20.                 <prop >PROPAGATION_REQUIRED</prop>   
  21.                 <prop >PROPAGATION_REQUIRED,readOnly</prop>   
  22.                 <prop key="*">PROPAGATION_REQUIRED</prop>   
  23.             </props>   
  24.         </property>   
  25.     </bean>   
  26.     <!-- 定義BeanNameAutoProxyCreator的Bean后處理器 -->   
  27.     <bean class="org.springframework.aop.framework.autoproxy.   
  28.     BeanNameAutoProxyCreator">   
  29.     <!-- 指定對(duì)滿足哪些bean name的bean自動(dòng)生成業(yè)務(wù)代理 -->   
  30.         <property name="beanNames">   
  31.               <!-- 下面是所有需要自動(dòng)創(chuàng)建事務(wù)代理的Bean -->   
  32.               <list>   
  33.                   <value>myService</value>   
  34.                   <!-- 下面還可增加需要增加事務(wù)邏輯的業(yè)務(wù)邏輯Bean -->   
  35.                 ...   
  36.               </list>   
  37.               <!-- 此處可增加其他需要自動(dòng)創(chuàng)建事務(wù)代理的Bean -->   
  38.         </property>   
  39.         <!-- 下面定義BeanNameAutoProxyCreator所需的攔截器 -->   
  40.         <property name="interceptorNames">   
  41.               <list>   
  42.                   <value>transactionInterceptor</value>   
  43.                   <!-- 此處可增加其他新的Interceptor -->   
  44.               </list>   
  45.         </property>   
  46.     </bean>   

 一旦增加了如上的配置片段,系統(tǒng)中的業(yè)務(wù)邏輯方法就有了事務(wù)邏輯。這種聲明式事務(wù)配置方式可以在不同的事務(wù)策略之間自由切換。
提示:盡量使用聲明式事務(wù)配置方式,而不要在代碼中完成事務(wù)邏輯。 

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多