<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    JAVA涂鴉
    關(guān)于JAVA的點(diǎn)點(diǎn)滴滴
    posts - 50,  comments - 689,  trackbacks - 0

    這一章包括:

    n????? 使用 DAO 模式創(chuàng)建抽象層。

    n????? 使用層的父型模式簡(jiǎn)化 resource cleanup (資源清除)代碼

    n????? spring 組織你的項(xiàng)目

    ?

    理解 Hibernate 的底層將需要很長(zhǎng)一段時(shí)間才能在你的項(xiàng)目上使用。但是在 Hibernate 庫的基礎(chǔ)之外,如 SessionFactory (會(huì)話工廠), Session (會(huì)話), mapping files ( 映射文件) hibernate Query Language(HQL) Hibernate 查詢語言),在一定高度組織一個(gè)應(yīng)用程序并不是總是那么清楚的。 你能在你的項(xiàng)目中應(yīng)用一些模式和好的經(jīng)驗(yàn)。一些好的經(jīng)驗(yàn)來自于社區(qū);而另外一些來自應(yīng)用于持久化的Java企業(yè)模式。這一章的目的就是帶給你這些。

    ??? 寫程序有點(diǎn)像用小朋友的 alphabet blocks (譯者注:一種表面有字母的積木)建塔。如果你是建個(gè)小塔,那么你不需要仔細(xì)關(guān)心是怎么堆的。但如果你建一個(gè)大的塔,那么你可能要站得更高,你需要稍微不同的技術(shù)設(shè)置。多一點(diǎn)計(jì)劃,多一點(diǎn)怎樣堆的技術(shù)和可能使用一些超強(qiáng)的粘合劑。

    ??? 無論是建立玩具塔還是寫軟件都要使用好的工具和技術(shù)。因此這一章就是怎樣建立一座高塔。我們將討論一些普通的模式: Data Access Object(DAO) 封裝底層數(shù)據(jù)操作 )和層的父型模式。另外, spring , 流行的開源項(xiàng)目將為簡(jiǎn)化你的代碼提供組織的工具。總之,這一章將給這個(gè)工具一個(gè)總的看法和怎樣簡(jiǎn)化你的 Hibernate 項(xiàng)目。

    ?

    章節(jié)目標(biāo):

    在這一章,你將完成一些幾點(diǎn):

    n???????? 創(chuàng)建抽象層,使用 DAO 模式集中 SQL 語句,因此簡(jiǎn)化客戶端對(duì)象使用。

    n???????? 使用層的父型模式改善 DAO 對(duì)象,簡(jiǎn)化 resource cleanup (資源清除)代碼。

    n???????? 使用 spring 組織和簡(jiǎn)化你的 DAO 代碼。

    ?

    前提條件:

    假設(shè)你已經(jīng)完成以下幾點(diǎn):

    n???????? 熟悉模式的概念。

    n???????? 理解 session (會(huì)話)和 transaction (事務(wù))的工作原理,特別是怎樣使用持久化被打開 session (會(huì)話)鏈接的對(duì)象。

    n???????? 你正在尋找一種能組織大型項(xiàng)目的技術(shù)。也就是說,使用好的框架代碼將利于項(xiàng)目的以后的擴(kuò)展。

    ?

    7.1 無處不在的 DAO 模式

    大多數(shù) Java/J2EE 開發(fā)者都或多或少熟悉 DAO 模式。它是 Sun 公司特地在 Java 藍(lán)圖中強(qiáng)調(diào)的核心模式之一,在許多 Java 書籍中都提到過。它是在使用持久化數(shù)據(jù)存儲(chǔ)的應(yīng)用程序中的采取的第一個(gè)首要模式。一般使用在使用 SQL 的應(yīng)用程序中,同樣也適用于 Hibernate 的應(yīng)用程序。

    ?

    7.1.1 集中 HQL

    DAO 模式的目的能在在一個(gè)簡(jiǎn)單問題的答案中找到:你的數(shù)據(jù)操作代碼放在哪里?如果你面對(duì)一個(gè)遺留程序而苦惱,因?yàn)檫@個(gè)程序中 SQL 代碼就像鳥槍發(fā)射那樣四處都是,而你又沒有這方面的經(jīng)驗(yàn)。其實(shí)這并沒什么。需要從新命名表中的列嗎?準(zhǔn)備好手中的槍,在整個(gè)程序中修改,以確保你沒有遺漏任何 SQL 語句。

    DAO 模式鼓勵(lì)開發(fā)者集中 SQL 語句。那么怎樣才是好的 SQL HQL 呢?在應(yīng)用程序中將 HQL 放在一個(gè)地方以便以后更容易維護(hù)和修改。新手可能不能很好的確定將 HQL 放在哪?他們將 HQL 放在DAO中。 Figure 7.1 顯示了 Event EventDao 怎樣和數(shù)據(jù)庫互動(dòng)。

    springdao1.jpg

    Figure 7.1 Event EventDao 與數(shù)據(jù)庫互動(dòng)的圖

    ?

    通過前面章節(jié)知道,一個(gè)健壯的對(duì)象查詢語句需要有錯(cuò)誤處理管理,事務(wù)和 resource cleanup (資源清除)。在余下的程序中最好隱藏以上那些。例如接下來的 Hibernate 程序,使程序更容易改變 ORM object/relational mapping 對(duì)象關(guān)系映射 )實(shí)現(xiàn)(例如:改變成 JDO 1。更重要的是,這個(gè)策略簡(jiǎn)化了客戶端怎樣和持久化層互動(dòng);他們不需要知道 session (會(huì)話), transaction (事務(wù))的邊界,或者在他們使用之后是否被清除。

    ?

    DAO 也有類型

    ??? 你能使用 DAO 兩種基本類型中的一種:

    n???????? 應(yīng)用級(jí) DAO(DAO per application) :在一個(gè)應(yīng)用中有一個(gè)中心的 DAO 對(duì)所有的實(shí)體對(duì)象添、刪、改、查。

    n???????? 類級(jí) DAO(DAO per class) :每個(gè)實(shí)體類都有自己的 DAO ,用于自身實(shí)例的添、刪、改、查。 Event 對(duì)象由 EventDao 負(fù)責(zé)。

    你也可以應(yīng)用其他鏡像變量,例如使用模塊級(jí) DAO(DAO per module) ,但是最終的選擇還是依賴于你有少個(gè)持久化對(duì)象。在有許多類的情況下,我們偏愛使用類級(jí)DAO策略。應(yīng)用級(jí) DAO 策略會(huì)出現(xiàn)“ bloatware ”類。第二,與類級(jí) DAO 命名對(duì)稱能更好的記憶。如果你需要找到 Event 類,你就能夠記得起它的 DAO EventDao 。最后,它滿足開-關(guān)原則,原則規(guī)定類將因?yàn)閿U(kuò)充而打開,因?yàn)樾薷亩P(guān)閉。你能夠添加一個(gè)新的持久化類,而不需要修改中心的 DAO 。因此,讓我們?cè)谑纠惺褂妙惣?jí) DAO

    ?

    簡(jiǎn)單的 DAO

    ??? Listing 7.1 顯示了一個(gè)簡(jiǎn)單的 DAO ,它能處理滿足大多數(shù)實(shí)體需要的基本的CRUD(添、刪、改、查)業(yè)務(wù)。除了這些功能,它還有一些功能,因此客戶端對(duì)象不用擔(dān)心。

    n???????? 包括業(yè)務(wù)級(jí) session session per operation ;每個(gè) session (會(huì)話)都有添、刪、改、查方法。

    n???????? 提供一個(gè)業(yè)務(wù)級(jí) transaction (事務(wù)) (transaction per operation) 。客戶端對(duì)象不用擔(dān)心開始和提交事務(wù)。

    n???????? Hibernate2.1 中,處理捕獲和 Hibernate 拋出的預(yù)期異常,將它們變?yōu)榉穷A(yù)期異常,將不會(huì)使客戶端代碼混亂。如果你使用 Hibernate3.x ,你能夠讓沒有從新拋出的非預(yù)期異常通過。( In Hibernate 2.x, handles catching and handling the checked exceptions that Hibernate throws, turning them into unchecked exceptions, which won’t clutter up client code. If you use Hibernate 3.x, you can just let the unchecked HibernateException s go without rethrowing .

    n???????? 輸入特性鮮明和明確的 DAO EventDat 僅為 Event 工作,意思就是客戶端代碼不必執(zhí)行手動(dòng)的操作。( Features strongly typed and explicit DAOs; the EventDao only works with Event s, meaning client code doesn’t have to perform manual casting.

    ?

    Listing 7.1 一個(gè)簡(jiǎn)單的有 添、刪、改、查方法的 EventDao

    ---------------------------------------------------------------------------------------------

    package ?com.manning.hq.ch07;
    ?
    import ?org.hibernate.HibernateException;
    import ?org.hibernate.Session;
    import ?org.hibernate.Transaction;
    import ?org.apache.commons.logging.Log;
    import ?org.apache.commons.logging.LogFactory;
    import ?com.manning.hq.ch07.Event;
    import ?com.manning.hq.ch07.HibernateFactory;
    import ?java.util.List;

    /**
    *?DAO管理持久Evnet
    */
    public ? class ?SimpleEventDao?{

    ??? Log?log?
    = ?LogFactory.getLog(SimpleEventDao. class );
    ??? private ?Session?session;
    ??? private ?Transaction?tx;

    ??? public ?SimpleEventDao()?{
    ??? ??? HibernateFactory.buildIfNeeded();
    // 初始化SessionFactory。
    ??? }
    ?
    ??? public ? void ?create(Event?event)? throws ?DataAccessLayerException?{
    ??? ??? try ?{
    ??? ??? ??? startOperation();
    // 打開Session和開始transaction
    ??? ??? ??? session.save(event);
    // 保存Event。
    ??? ??? ??? tx.commit();
    ??? ??? }?
    catch ?(HibernateException?e)?{
    ??? ??? ??? handleException(e);Rolls?back和拋出異常。
    ??? ??? }?
    finally ?{
    ??? ??? ??? HibernateFactory.close(session);
    ??? ??? }
    ??? }

    ??? public ? void ?delete(Event?event)? throws ?DataAccessLayerException?{
    ??? ??? try ?{
    ??? ??? ??? startOperation();
    ??? ??? ??? session.delete(event);
    ??? ??? ??? tx.commit();
    ??? ??? }?
    catch ?(HibernateException?e)?{
    ??? ??? ??? handleException(e);
    ??? ??? }?
    finally ?{
    ??? ??? ??? HibernateFactory.close(session);
    ??? ??? }
    ??? }

    ??? public ?Event?find(Long?id)? throws ?DataAccessLayerException{

    ??? ??? Event?event?
    = ? null ;
    ??? ??? try ?{
    ??? ??? ??? startOperation();
    ??? ??? ??? event?
    = ?(Event)?session.load(Event. class ,?id);
    ??? ??? ??? tx.commit();
    ??? ??? }?
    catch ?(HibernateException?e)?{
    ??? ??? ??? handleException(e);
    ??? ??? }?
    finally ?{
    ??? ??? ??? HibernateFactory.close(session);
    ??? ??? }
    ??? ??? return ?event;
    ??? }

    ??? public ? void ?update(Event?event)? throws ?DataAccessLayerException?{
    ??? ??? try ?{
    ??? ??? ??? startOperation();
    ??? ??? ??? session.update(event);
    ??? ??? ??? tx.commit();
    ??? ??? }?
    catch ?(HibernateException?e)?{
    ??? ??? ??? handleException(e);
    ??? ??? }?
    finally ?{
    ??? ??? ??? HibernateFactory.close(session);
    ??? ??? }
    ??? }

    ??? private ? void ?handleException(HibernateException?e)? throws ?DataAccessLayerException?{
    ??? ??? HibernateFactory.rollback(tx);
    ??? ??? throw ? new ?DataAccessLayerException(e);
    ??? ??? // ?二選一,你能夠從新拋出,就像…
    ??? ??? // ?throw?e;
    ??? }

    ??? private ? void ?startOperation()? throws ?HibernateException?{
    ??? ??? session?
    = ?HibernateFactory.openSession();
    ??? ??? tx?
    = ?session.beginTransaction();
    ???? }
    }


    package ?com.manning.hq.ch07;

    public ? class ?DataAccessLayerException? extends ?RuntimeException?{
    // 其他的構(gòu)造函數(shù)省略。
    ??? public ?DataAccessLayerException(Throwable?cause)?{
    ??? ??? super (cause);
    ??? }
    }

    ---------------------------------------------------------------------------------------------

    ??? SimpleEventDao 是個(gè)極其簡(jiǎn)單的 DAO ,它有添,刪,改,查四種方法。每種方法在一個(gè) transaction (事務(wù)),打開和關(guān)閉一個(gè) session (會(huì)話)范圍內(nèi)處理業(yè)務(wù)。它是明確的,也就是說每個(gè) Event 都有獨(dú)有的業(yè)務(wù)處理,因此客戶端類不需要再處理這些了。當(dāng)這個(gè)實(shí)現(xiàn)是簡(jiǎn)單的(以后可能隨著擴(kuò)展會(huì)變大),客戶端代碼在運(yùn)行 event 時(shí)代碼就會(huì)變得很短。( While this implementation is simple (perhaps overly so, as we will explore here later), it greatly shortens the client code that works with events. )因此創(chuàng)建和查詢一個(gè)event就象下面的一樣簡(jiǎn)單:---------------------------------------------------------------------------------------------

    Event?event? = ? new ?Event();
    event.setName(
    " A?new?Event " );
    EventDao?eventDao?
    = ? new ?EventDao();
    eventDao.create(event);
    Event?foundEvent?
    = ?eventDao.find(event.getId());

    ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    正如你看到的,不需要處理凌亂的異常,這里也不需要處理 resource cleanup (資源清除)。現(xiàn)在讓我們討論更多一些這個(gè)實(shí)現(xiàn)出現(xiàn)的問題,并且我們?cè)撛鯓犹岣咚?span lang="EN-US">

    ?

    7.2 分析 DAO

    ??? 我們?cè)谇懊嬲鹿?jié)練習(xí)的簡(jiǎn)單的DAO實(shí)現(xiàn)出現(xiàn)了一些問題,有些你或許已經(jīng)遇到。讓我們看一看。

    ?

    7.2.1 boilerplate code 樣板代碼)

    Listing 7.1 包括許多資源管理和異常處理代碼。每個(gè)方法都有打開 session (會(huì)話),開始事務(wù),執(zhí)行自己的商務(wù)業(yè)務(wù),提交事務(wù),事務(wù)回滾,最后關(guān)閉 session (會(huì)話)。每個(gè)方法基本就像下面那樣:

    -------------------------------------------------------------------------------

    ? try ?{
    ???? startOperation();
    ???? session.save(event);
    ???? tx.commit();
    ?}?catch?(HibernateException?e)?{
    ???? handleException(e);
    ?}?finally?{
    ???? HibernateFactory.close(session);
    ?}

    -------------------------------------------------------------------------------

    Session.save(event) 這一行是每個(gè)方法中唯一改變的。甚至 refactoring 幾個(gè)便利的方法(譯者注:找了不少詞典,都沒有找到“ refactor ”),如 startOperation () handleException () ,都不能完全擺脫你的樣板代碼。( Even refactoring out a few convenience methods,such as startOperation() and handleException() , doesn’t completely rid you of boilerplate code )一個(gè) potential solution (潛在的解決方案)就是在7.3節(jié)討論的層的父型模式。

    ?

    7.2.2 P otential duplication 潛在的復(fù)制)

    ??? 增加一個(gè)新的 DAO 變得很簡(jiǎn)單,只需要復(fù)制和粘貼。如果你需要其他的 DAO ,如 LocationDao , 我們將復(fù)制和粘貼 EventDao ,然后在每個(gè)方法中改變關(guān)聯(lián)的少許幾行代碼。因?yàn)槲覀冎缽?fù)制是所有程序的惡魔之首,顯然需要做點(diǎn)事情。建立層的父型模式是非常有幫助的。

    ?

    7.2.3 游離對(duì)象

    ??? 因?yàn)槊總€(gè)方法都是與單一的 session (會(huì)話)和 transaction (事務(wù))運(yùn)作的,與 DAO 運(yùn)作的所有的 Event 是嚴(yán)格的游離對(duì)象。這個(gè)行為也許是美好的,但它不能夠利用 Hibernate 的自動(dòng)臟對(duì)象檢查和 session-level object cache (會(huì)話級(jí)對(duì)象緩存)。例如,假如客戶端這樣寫:

    ---------------------------------------------------------------------------------------------

    Event?foundEvent? = ?eventDao.find(event.getId());
    foundEvent.setDuration(
    30 );
    eventDao.update(foundEvent);

    ---------------------------------------------------------------------------------------------

    Find 運(yùn)行在一個(gè) session (會(huì)話)中, update 運(yùn)行在另一個(gè) session (會(huì)話)中。它一定會(huì)運(yùn)行,但如果 find update 能以某種方法共享一個(gè) session (會(huì)話)那才是真正的好。并且,它能更好的避免在 session (會(huì)話)周圍的凌亂的方法署名。當(dāng)它運(yùn)作時(shí),它是難看的,因此我們不想看到下面這樣:

    ---------------------------------------------------------------------------------------------


    Session?session?
    = ?HibernateFactory.openSession();
    Event?foundEvent?
    = ?eventDao.find(event.getId(),?session);
    foundEvent.setDuration(
    30 );
    eventDao.update(foundEvent,?session);
    ?

    ---------------------------------------------------------------------------------------------

    ??? 給方法增加 session (會(huì)話)參數(shù),強(qiáng)制責(zé)任,管理和在客戶端代碼共享 session (會(huì)話)。這樣會(huì)帶來重復(fù),復(fù)雜和潛在的錯(cuò)誤。

    ??? 這個(gè)問題的一個(gè)潛在的解決方案是眾所周知的 Thread Local Session 模式。這個(gè)模式將在第八章介紹,因此我們不會(huì)在這里直接介紹。我們改用另外一種框架練習(xí), spring ,它使用 Thread Local Session 模式,在下面會(huì)有介紹。

    ?

    7.3 層的父型模式

    ??? 常規(guī)的 J2EE 智者認(rèn)為應(yīng)用程序被劃分成不同的層。假設(shè)你的應(yīng)用程序已經(jīng)有這些層了,當(dāng)然,依賴于你所讀的書。一些普遍的層的選擇如下:

    n???????? 表示層,這里是所有用戶交互和表示的代碼。

    n???????? 領(lǐng)域?qū)樱@里是邏輯的商務(wù)代碼。

    n???????? 持久層,這里是數(shù)據(jù)存儲(chǔ)操作的代碼。

    ??? 不管你的應(yīng)用程序是否有這些層,在層中的每個(gè)對(duì)象都有某些共同的代碼能夠被固定到一個(gè)類中,這一點(diǎn)是非常普通的。這個(gè)原因出現(xiàn)了層的父型模式,每一層都有“一種類型,這種類型作為所有的層中的類型的父型”2。你能夠使用父型模式簡(jiǎn)化你的 DAO

    ??? Figure7.2 用一個(gè)簡(jiǎn)單的層次顯示了層的父型 AbstractDao ,它提供了 protected 方法,在子類中可以覆蓋和改為 public

    springdao2.JPG

    ??? Figure 7.2 層的父型 AbstractDao 的圖

    ??? 下一步就是創(chuàng)建 AbstractDao ,下一節(jié)將介紹。

    ?

    7.3.1 創(chuàng)建 AbstractDao

    ??? 第一步是創(chuàng)建你的父型, AbstractDao ,所有的 DAO 最后將擴(kuò)展。 Listing 7.2 顯示了類的內(nèi)容。

    Listing 7.2 層的父型實(shí)現(xiàn), AbstractDao ,它有所有 DAO 的共同的業(yè)務(wù)。

    -----------------------------------------------------------------------------------------
    ??

    package?com.manning.hq.ch07;

    import?org.hibernate.HibernateException;
    import?org.hibernate.Query;import?org.hibernate.Session;
    import?org.hibernate.Transaction;
    import?java.util.List;
    ??
    /**
    *?層的父型處理所有DAO共同的運(yùn)作
    */

    public?abstract?class?AbstractDao{

    ??? private?Session?session;
    ??? private
    ?Transaction?tx;

    ??? public?AbstractDao()?{
    ??? ??? HibernateFactory.buildIfNeeded();
    ??? }

    ??? protected?void?saveOrUpdate(Object?obj){//運(yùn)作是普通的,而不是特指域對(duì)象
    ??? ??? try?{
    ??? ??? ??? startOperation();
    ??? ??? ??? session.saveOrUpdate(obj);
    ??? ??? ??? tx.commit();
    ??? ??? }?
    catch?(HibernateException?e)?{
    ??? ??? ??? handleException(e);
    ??? ??? }?
    finally?{
    ??? ??? ??? HibernateFactory.close(session);
    ??????? }
    ??? }

    ???
    protected?void?delete(Object?obj)?{
    ??? ??? try?{
    ??? ??? ??? startOperation();
    ??? ??? ??? session.delete(obj);
    ??? ??? ??? tx.commit();
    ??? ??? }?
    catch?(HibernateException?e)?{
    ??? ??? ??? handleException(e);
    ??? ??? }?
    finally?{
    ??? ??? ??? HibernateFactory.close(session);
    ??? ??? }
    ??? }

    ??? protected
    ?Object?find(Class?clazz,?Long?id){//查找基于類和id的持久化對(duì)象

    ??? ??? Object?obj?
    =?null;

    ??? ??? try?{
    ??? ??? ??? startOperation();
    ??? ??? ??? obj?
    =?session.load(clazz,?id);
    ??? ??? ??? tx.commit();
    ??? ??? }?
    catch?(HibernateException?e)?{
    ??? ??? ??? handleException(e);
    ??? ??? }?
    finally?{
    ??? ??? ??? HibernateFactory.close(session);
    ??? ??? }
    ??? ??? return?obj;
    ??? }

    ??? protected?List?findAll(Class?clazz)?{

    ??? ??? List?objects?
    =?null;

    ??? ??? try?{
    ??? ??? ??? startOperation();
    ??? ??? ??? Query?query?
    =?session.createQuery("from?"?+?clazz.getName());
    ??? ??? ??? objects?
    =?query.list();
    ??? ??? ??? tx.commit();
    ??? ??? }?
    catch?(HibernateException?e)?{
    ??? ??? ??? handleException(e);
    ??? ??? }?
    finally?{
    ??? ??? ??? HibernateFactory.close(session);
    ??? ??? }
    ??? ??? return?objects;
    ??? }

    ??? protected?void?handleException(HibernateException?e)??throws?DataAccessLayerException?{
    ??? ??? HibernateFactory.rollback(tx);
    ? ?? ? throw?new?DataAccessLayerException(e);
    ??? }

    ??? protected?void?startOperation()?throws?HibernateException?{
    ??? ??? session?
    =?HibernateFactory.openSession();
    ??? ??? tx?
    =?session.beginTransaction();
    ??? }
    }


    --------------------------------------------------------------------------------------------

    ????在這個(gè)Listing中,你看到了共同的CRUD方法,包括save,?find和delete方法都放入AbstractDao類中。他們是 generic和protected,因此子類能夠調(diào)用它們。這樣你的EventDao將簡(jiǎn)化。這里是一個(gè)簡(jiǎn)單的簡(jiǎn)化了的方法:

    ---------------------------------------------------------------------------------------------

    public?????class???ImprovedEventDao???extends???AbstractDao?{
    //??其他的方法省略
    ??? public???void??create(Event?event)??throws??DataAccessLayerException?{
    ??? ??? saveOrUpdate(event);
    ??? }

    ??? public??Event?find(Long?id)??throws??DataAccessLayerException?{
    ??? ??? return??(Event)?find(Event.?class?,?id);
    ??? }
    }
    --------------------------------------------------------------------------------------------
    ??? ImprovedEventDao的僅有的責(zé)任就是執(zhí)行業(yè)務(wù)和委托調(diào)用父類。樣板代碼和潛在的復(fù)制的雙重問題得到解決。當(dāng)我們?cè)黾右粋€(gè)新的實(shí)體對(duì)象時(shí),如:Locations或者Speakers,添加新的DAO
    --使用AbstractDao作為層的父型,將是非常迅速的。
    --------------------------------------------------------------------------------------------

    public?classImprovedLocationDao extendsAbstractDao?{
    //其他的方法省略
    ??? publicvoid create(Location?location) throws??DataAccessLayerException?{
    ??? ??? saveOrUpdate(location);
    ??? }

    ??? publicLocation?find(Long?id)??throws??DataAccessLayerException?{
    ??? ??? return??(Location)?find(Location.?class?,?id);
    ??? }
    }
    ---------------------------------------------------------------------------------------------

    通過層的父型的介紹,剩余的問題得到解決, DAO 與游離對(duì)象運(yùn)作。我們想在我們的方法中共享會(huì)話,甚至通過不同的 DAO 。為了做到這一點(diǎn),我們將學(xué)習(xí)一個(gè)新的流行框架, Spring .

    ?

    7.4 Spring 框架

    ?????? 我們已經(jīng)注意到已經(jīng)定義的 DAO 實(shí)現(xiàn)中的一些缺陷。復(fù)制資源管理代碼和使用業(yè)務(wù)級(jí)的 session session per operation )使解決方案會(huì)比我們需要的更加復(fù)雜,而且也沒有我們喜歡的靈活。我們一定能過編寫更好的更健壯的解決方案。幸運(yùn)的是,我們不需要擔(dān)心 --- 一個(gè)優(yōu)秀的開源解決方案, Spring 框架已經(jīng)提供給我們了。

    ?????? Spring 解決了比幫助我們解決 Hibernate 更多的問題。這是事實(shí),“一個(gè)輕量級(jí)的容器,允許開發(fā)者連接商務(wù)對(duì)象, DAO 和資源就像 JDBC DataSources Hibernate SessionFactories 。” 3?? 它使用中心 XML 配置文件去管理資源,甚至它自身的 web MVC 框架( Model-View-Controller )。 Spring 是普通的框架,就是說它可以使用在許多不同的位置中。如果你不熟悉 Spring ,你也許會(huì)想我該怎樣使用它,你也許認(rèn)為他僅僅是個(gè)框架,假設(shè)用來提供某種編譯。因此我們將在這里展示。

    ?????? Spring 已經(jīng)被考慮成熟的分割為穩(wěn)固的集中的若干模塊,包括我們先前提到的 MVC web 框架, JDBC 支持, aspect-oriented programming AOP )( 面向剖面編程 )和 ORM 模塊。這樣就允許你使用其中你需要的,而不用學(xué)習(xí)或者考慮其他的。為了我們的目的,我們將僅僅學(xué)習(xí)怎樣簡(jiǎn)化你的 Hibernate 代碼,也就是 ORM 模塊。最佳的開始的地方是模板。

    ?????? 首先,你需要獲得 Spring 框架的副本,你可以在 www.springframework.org 找到。解壓到 applications 目錄下的 Hibernate 旁邊。 Spring 有許多可選擇的包,但為了簡(jiǎn)單,你只需要考慮一個(gè) JAE 包,它就是 applications\spring-framework-1.2-rc2\dist\spring.jar 文件。將它加入到 build.xml 文件的 classpath 中。

    -------------------------------------------------------------------------------------------------------------------------

    < property?name = " spring.version " ?value = " 1.2-rc2 " />
    < property?name = " spring.lib.dir "
    ??? value
    = " ${applications.dir}/spring-framework-${spring.version} " />
    < path?id = " spring.lib.path " >
    < fileset?dir = " ${spring.lib.dir}\dist " >
    < include?name = " **/spring.jar " />
    </ fileset >
    </ path >
    < path?id = " runtime.classpath " >
    // ?其他的?paths?省略。
    < path?refid = " spring.lib.path " />
    < path >

    -------------------------------------------------------------------------------------------------------------------------

    ?????? 這個(gè)代碼配置了 Spring 使它能過在我們的示例項(xiàng)目中使用。 Hibernate3 最近已經(jīng)發(fā)布(在出版的時(shí)候),其他支持項(xiàng)目如 Spring 也跟上提供支持了。這里我們使用最新的版本。另外,因?yàn)?/span> Spring 不得不支持 Hibernate 2 Hibernate 3, 一個(gè)新的包, org.springframework.orm hibernate3 已經(jīng)將它加入到 Hibernate3 的項(xiàng)目中了。接下來,讓我們看看 Spring 怎樣被使用來簡(jiǎn)化我們的示例項(xiàng)目。

    ?

    7.4.1 在模板中是什么

    ??? Spring 給我們提供了 Hibernate 業(yè)務(wù)的模板。模板有什么,我們?yōu)槭裁葱枰看鸢妇驮谖覀兊?/span> SimpleEventDao 中的 create 方法中。

    --------------------------------------------------------------------------------------------

    protected ? void ?create(Event?event)?{
    ??? try ?{
    ??? ??? startOperation();
    ??? ??? session.save?(event);
    ??? ??? tx.commit();
    ??? }?
    catch ?(HibernateException?e)?{
    ??? ??? handleException(e);
    ??? }?
    finally ?{
    ??? ??? HibernateFactory.close(session);
    ??? }
    }

    --------------------------------------------------------------------------------------------

    ??? 如果你注意了,方法中只調(diào)用一個(gè)真正的事件是: save ()。其他的每一行,我們喜歡稱為“ excise (稅)”。 excise (稅)是我們?yōu)榱斯ぷ鞑坏貌蝗プ龅念~外的事情,這些事情不是真正的直接重要。它就像當(dāng)你開車去上班,駕駛的實(shí)際行動(dòng)才是重要的事情;開車庫門和倒車都是 excise (稅)任務(wù),它可以看成同等重要,也可以忽略或者自動(dòng)完成。

    ?????? 在程序中, excise (稅)是框架或者語言安全需要,你不得不編寫的代碼。一個(gè)典型的 excise (稅)例子就是 Java 除去了內(nèi)存管理。 Spring 能夠除去 Hibernate JDBC 要求之下的資源管理 excise (稅)的一部分。

    ?????? 一般情況下,當(dāng)你復(fù)制代碼,你能夠 refactor 一個(gè)方法或類。這里,因?yàn)閺?fù)制代碼是商務(wù)方法周圍的 resource? cleanup (資源清理),使它更加復(fù)雜。現(xiàn)在有模板可用。導(dǎo)入 Spring 提供的類: org.springframework.orm.hibernate3.HibernateTemplate 。它包含了所有資源處理代碼以致于你僅只要寫一個(gè)重要方法就可以了。我們的 create() 方法能夠這樣寫:

    ----------------------------------------------------------------------------------------------------------------------------------------------------

    import ?org.hibernate.Hibernate;
    import ?org.hibernate.SessionFactory;
    import ?org.springframework.orm.hibernate3.HibernateTemplate;

    protected ? void ?create(Event?event)?{
    ??? SessionFactory?sf?
    = ?HibernateFactory.getSessionFactory();
    ??? HibernateTemplate?template?
    = ? new ?HibernateTemplate(sf);
    ??? template.saveOrUpdate(event);
    }

    -------------------------------------------------------------------------------------------------------------------------

    注意我們沒有做什么:

    n???????? SessionFactory 獲得 session

    n???????? 開始事物

    n???????? 捕獲預(yù)期異常和將他轉(zhuǎn)變?yōu)榉穷A(yù)期異常( 3.x 版本不需要, 2.x 則需要)

    n???????? 提交事物

    n???????? 將改變輸入數(shù)據(jù)庫

    n???????? 關(guān)閉 session

    這里有許多事情我們不需要擔(dān)心,因?yàn)?/span> HibernateTemplate 已經(jīng)照顧到了。你或許注意到 HibernateTemplate 看上去像包裹 Session 的周圍。實(shí)際上,可以把 HibernateTemplate 理解為一個(gè)“聰明”的 Session ,它知道怎樣打開,關(guān)閉和在運(yùn)行完清除。在之前默認(rèn)的情況下,它使用的是方法級(jí)事務(wù)( transaction per method )模式。這是非常簡(jiǎn)單的,但你將在后面看到你也能夠改事務(wù)的范圍。這里有兩個(gè)基本的方式和 Hibernatetemplate 互動(dòng):通過 convenience mehod (便利的方法)和重要的 callback (回調(diào))。

    ?

    Convenience methods (便利的方法)

    ??? 簡(jiǎn)單的事情將變得容易。在許多案例中,你想用 Session (會(huì)話)做什么是非常重要的:執(zhí)行保存,更新有力對(duì)象,或者運(yùn)行 HQL 查詢。沒有一個(gè)需要禮儀來獲得完成。 HibernateTemplate 類提供了基本的方法,因此一行代碼就可以簡(jiǎn)單的調(diào)用業(yè)務(wù)。這里有一些方法的簡(jiǎn)單樣例:

    ---------------------------------------------------------------------------------------------

    import ?com.manning.hq.ch07.Event;
    import ?com.manning.hq.ch07.HibernateFactory;
    import ?org.springframework.orm.hibernate3.HibernateTemplate;
    import ?java.util.List;

    SessionFactory?sessionFactory?
    = HibernateFactory.getSessionFactory();
    // ?創(chuàng)建連接?SessionFactory?的模板
    HibernateTemplate?template?
    = new ?HibernateTemplate(sessionFactory);
    Event?event1?
    = ? new ?Event();
    event1.setName(
    " Event?1 " );
    Event?event2?
    = ? new ?Event();
    event2.setName(
    " Event?2 " );

    ??? try ?{
    ??? ??? template.save?(event1);???
    // ?在一個(gè)事務(wù)中保存?event
    ??? ??? template.save?(event2);
    // ?加載一個(gè)?event
    ??? ??? Event?obj?
    = ?(Event)?template.load(Event. class ,?event1.getId());
    ??? ??? System.out.println(
    " Loaded?the?event " ? + ?obj.getName()); // ?找到所有的?event
    ??? ??? List?events?
    = ?(List)?template.find( " from?Event " );
    ??? ??? System.out.println(
    " #?of?Events? " ? + ?events.size());
    ??? }?
    finally ?{
    ??? ??? template.delete(event1);?
    // ?刪除一個(gè)?event
    ??? ??? template.delete(event2);
    ??? }

    ---------------------------------------------------------------------------------------------

    convenience methods 便利的方法)是有代表性的正確的命名,就像 Session (會(huì)話)中的方法一樣。他們能被 session (會(huì)話)作為 one-for-one (一對(duì)一)復(fù)位直接調(diào)用,沒有任何雜亂的 resource cleanup (資源清除)代碼障礙。

    ?

    Callback (回調(diào))

    ??? 復(fù)雜的事情可能有好處。不是所有的在單個(gè) transaction ( 事務(wù))中的單個(gè) query (查詢)能夠輕松的減少業(yè)務(wù)。在這些業(yè)務(wù)中, spring 提供了 Callback 接口。它允許你在將要執(zhí)行的模板中編寫 callback 方法。例如,如果你想構(gòu)建一個(gè)復(fù)雜的 query (查詢),更新一些數(shù)據(jù),然后保存,所有的都在一個(gè)業(yè)務(wù)中:

    -------------------------------------------------------------------------------------------

    import ?org.hibernate.HibernateException;
    import ?org.springframework.orm.hibernate3.HibernateCallback;
    import ?java.sql.SQLException;
    import ?org.hibernate.Query;
    import ?java.util.List;
    import ?java.util.Iterator;
    import ?com.manning.hq.ch07.Event;?

    template.execute(
    new ?HibernateCallback()?{
    ??? public ?Object?doInHibernate(Session?session)? throws ?HibernateException,?SQLException?{
    ?? ??? Query?query?
    = ?session.createQuery( " from?Event " );
    ??? ??? query.setMaxResults(
    2 );
    ??? ??? List?events?
    = ?query.list();
    ??? ??? for ?(Iterator?it? = ?events.iterator();?it.hasNext();)?{
    ??? ??? ??? Event?event?
    = ?(Event)?it.next();
    ??? ??? ??? event.setDuration(
    60 );
    ??? ??? }
    ??? ??? return ? null ;
    ??? }
    })?;

    ---------------------------------------------------------------------------------------------

    這里, Callback 接口使用了匿名內(nèi)部類, HibernateCallback ,定義了一個(gè)單一的方法, doInHibernate() 。你可以編寫方法主體,然后提交 HibernateCallback 對(duì)象給模板,然后執(zhí)行。模板處理資源管理代碼,讓你只需要編寫任務(wù)的 query (查詢)邏輯。

    ?

    7.4.2 Beans 和 它們的 factories (工廠)

    你已經(jīng)看到能夠程序化使用 Spring 去減少 resource cleanup (資源清除)代碼。另外i,它能過更好的組織項(xiàng)目。 Spring 的慣例的說法是“輕量級(jí)”容器。它勝任執(zhí)行和配置簡(jiǎn)單的 JavaBeans 。它基本扮演構(gòu)建和配置你應(yīng)用程序中的 beans 的工廠角色。意思是它能夠被使用去配置大多數(shù)現(xiàn)存的 architectures (框架)和庫,包括 Hibernate

    ?

    中心的配置文件

    ??? 在這一點(diǎn)上,你將通過組合使用 hibernate.cfg.xml 文件( declaratively 聲明性的 ))和使用靈活的編程方式,如HibernateFactory來配置HibernateSpring提供了另外一個(gè)方法整體聲明配置Hibernate。使用Spring的最大好處就是你能夠減少編程配置需要的元素。

    ?

    Spring 能夠讀用一般配置格式編寫的 XML 文件。 XML 指定了怎樣連接不同對(duì)象,包括 DataSource (數(shù)據(jù)源), SessionFactory 和所有的 DAOs 。一旦你配置了文件,你就能夠?qū)⑺鳛椴檎?/span> DAOs 的中心“票據(jù)交換所”使用。例如,在 classpath root (根部)創(chuàng)建一個(gè)叫 applicationContext.xml 文件。就像 listing7.3 所顯示那樣。

    ?

    listing7.3 ApplicationContext.xml ,定義了 DataSource (數(shù)據(jù)源), SessionFactory DAO

    -------------------------------------------------------------------------------

    ?? <? xml?version = " 1.0 " ?encoding = " UTF-8 " ?>

    ? <! DOCTYPE?beans?PUBLIC

    ??? ? " -//SPRING//DTD?BEAN//EN "

    ??? ? " http://www.springframework.org/dtd/spring-beans.dtd " >

    ??? <
    beans >
    ??? ??? < bean?id = " dataSource " class = " org.apache.commons.dbcp.BasicDataSource " ????? ??? destroy - method = " close " > ???①
    ??? ??? < property?name = " driverClassName " >
    ??? ??? ??? < value > com.mysql.jdbc.Driver </ value >
    ??? ??? </ property >
    ??? ??? < property?name = " url " >
    ??? ??? ??? < value > jdbc:mysql: // localhost/events_calendar</value>
    ??? ??? </ property >
    ??? ??? < property?name = " username " >
    ??? ??? ??? < value > root </ value >
    ??? ??? </ property >
    ??? ??? < property?name = " password " >
    ??? ??? ??? < value ></ value >
    ??? ??? </ property >
    ??? ??? </ bean >

    ??? ??? < bean?id = " factory " class = " org.springframework.orm.hibernate3.LocalSessionFactoryBean " > ?②
    ??? ??? < property?name = " mappingResources " >
    ??? ??? ??? < list >
    ??? ??? ??? ??? < value > com / manning / hq / ch07 / Event.hbm.xml </ value >
    ??? ??? ??? ??? < value > com / manning / hq / ch07 / Location.hbm.xml </ value >
    ??? ??? ??? </ list >
    ??? ??? </ property >
    ??? ??? < property?name = " hibernateProperties " >
    ??? ??? ??? < props >
    ??? ??? ??? ??? < prop?key = " hibernate.dialect " > org.hibernate.dialect.MySQLDialect </ prop >
    ??? ??? ??? ??? < prop?key = " hibernate.show_sql " > false </ prop >
    ??? ??? ??? </ props >
    ??? ??? </ property >
    ??? ??? < property?name = " dataSource " > ???③
    ??? ??? ??? < ref?bean = " dataSource " />
    ??? ??? </ property >
    ??? ??? </ bean >

    ??? ??? < bean?id = " eventDao " class = " com.manning.hq.ch07.EventSpringDao " > ????④
    ??? ??? < property?name = " sessionFactory " > ?????⑤
    ??? ??? ??? < ref?bean = " factory " ? />
    ??? ??? </ property >
    ??? ??? </ bean >
    ??? </ beans >

    -------------------------------------------------------------------------------

    listing7.3 解釋

    ??? 配置一個(gè)基本的數(shù)據(jù)源,它使用由 Hibernate 發(fā)布的 Apache Commons database connection pool (DBCP)

    ?????? 配置一個(gè) SessionFactory ,構(gòu)建在 Spring SessionFactory wrapper, LocalSessionFactoryBean 。當(dāng) Spring 讀取這個(gè)文件時(shí),它就構(gòu)建一個(gè) SessionFactory SessionFactory 存儲(chǔ)在 Key factory

    ??????? 連接 SessionFactory 和數(shù)據(jù)源。

    ??????? 配置你的 EventSpringDao eventDao

    ??????? 連接 DAO session factory 。他允許 DAO 打開 session 和發(fā)布 queries

    -------------------------------------------------------------------------------------------------------------------------

    Listing 7.3 XML 配置文件列舉了所有能夠經(jīng)常改變?cè)敿?xì)內(nèi)容。它完成了許多與 hibernate.cfg.xml 所作的相同的事情,也為我們構(gòu)建了 SessionFactory ,這一點(diǎn)將在下一節(jié)看到。

    ?

    構(gòu)建 AppicationContext

    ??? 你剛剛創(chuàng)建的 applicationContext.xml 詳細(xì)的描述了怎樣構(gòu)建 session 工廠。它基本上可以一對(duì)一的替換你所看到的 HibernateFactory 使用的 hibernate.cfg.xml 。它定義了通常在 hibernate.cfg.xml 中的屬性和映射文件。在我們先前的示例代碼中,你需要構(gòu)建 SessionFactory ,或者通過你的 EventDao 對(duì)象連接 SessionFactory Spring 顛覆了這個(gè)概念。 Spring 為你構(gòu)建了 EventDao ,你需要詢問 EventDao 的首選項(xiàng),就像:

    ---------------------------------------------------------------------------------------------

    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import ?com.manning.hq.ch07.Event;

    ClassPathXmlApplicationContext?ctx?
    = ? new
    ClassPathXmlApplicationContext(
    " applicationContext.xml " );
    EventSpringDao?eventDao?
    = (EventSpringDao)?ctx.getBean( " eventDao " ,?EventSpringDao. class );
    Event?event?
    = ? new ?Event();
    eventDao.saveOrUpdate(event);
    --------------------------------------------------------------------------------------------

    ClasspathXmlApplicationContext 看上去 classpath 中,因?yàn)榕渲梦募拿衷?/span> instruction 中已提供( The ClasspathXmlApplicationContext looks in the classpath for the name of the configuration file provided in the instructions. )在這個(gè)案例中, applicationContext.xml classpath root (根)。你能夠從 application context 通過名字請(qǐng)求 bean getBean ()方法有兩個(gè)參數(shù): bean 的名字( eventDao ),你期望的類的類型( EventSpringDao )。

    在此之下, Spring 構(gòu)建了 SessionFactory 并將所有的 Bean 連接在一起。我們更早的認(rèn)識(shí)到 Spring Javabean 一起工作。所有的在 applicationContext.xml 文件中的 <bean> 元素都需要 JavaBean 。這包括了象下面的 EventSpringDao

    -------------------------------------------------------------------------------------------------------------------------

    public ? class ?EventSpringDao? extends ?AbstractSpringDao{
    ??? public ?EventSpringDao(){}
    ??? public ?Event?find(Long?id){
    ??? ??? return ?(Event)? super .find(Event. class ,?id);
    ??? }
    ??? // ?Other?methods?excluded
    }

    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    ???????? 另外更早的認(rèn)識(shí)到的好處是, Spring 提供了 org.springframework.orm.hibernate3.support.HibernateDaoSupport , 應(yīng)用 Dao 層的父型。她管理了 SessionFactory 和一些有用的方法去處理 Session Logging HibernateTemplate 。這有這些方法的示例:

    -------------------------------------------------------------------------------

    public ? abstract ? class ?HibernateDaoSupport? implements ?InitializingBean?{
    ??? protected ? final ?Log?logger;
    ??? private ?HibernateTemplate?hibernateTemplate;
    ??? public ? final ? void ?setSessionFactory(SessionFactory?sessionFactory);
    ??? public ? final ?SessionFactory?getSessionFactory();
    ??? public ? final ? void ?setHibernateTemplate(HibernateTemplate?hibernateTemplate);
    ??? public ? final ?HibernateTemplate?getHibernateTemplate(); ? ??? ??? ????? ??? ??? ??? ??? ??? ?? ??? ??? protected ? final ?Session?getSession()? throws? ??? DataAccessResourceFailureException,?IllegalStateException;
    ??? protected?final?void?closeSessionIfNecessary(Session?session);
    }

    -----------------------------------------------------------------------------------

    他提供了一些基本的方法,但我們選擇重寫 HibernateDaoSupport 對(duì)象,為了 提供更多的便利方法。 Listing7.4 顯示了改變的類。

    Listing 7.4 你的應(yīng)用的層的父型 DAOs

    --------------------------------------------------------------------------------------------

    package ?com.manning.hq.ch07;

    import ?java.util.List;
    import ?org.springframework.orm.hibernate3.support.HibernateDaoSupport;

    public ? abstract ? class ?AbstractSpringDao? extends ?HibernateDaoSupport{
    ??? public ?AbstractSpringDao()?{?}
    ??? protected ? void ?saveOrUpdate(Object?obj)?{
    ??? ??? getHibernateTemplate().saveOrUpdate(obj);
    ??? }

    ??? protected ? void ?delete(Object?obj)?{
    ??? ??? getHibernateTemplate().delete(obj);
    ??? }
    ??? protected ?Object?find(Class?clazz,?Long?id)?{
    ??? ??? return ?getHibernateTemplate().load(clazz,?id);
    ??? }

    ??? protected ?List?findAll(Class?clazz)?{
    ??? ??? return ?getHibernateTemplate().find( " from? " ? + ?clazz.getName());
    ??? }
    }

    ------------------------------------------------------------------

    重點(diǎn)注意的是 AbstractSpringDao 使用它的父類 sessionFactory 成員。 HibernateDaoSupport 提供了 getter setter 方法, Spring 使用 setter 方法去連接 SessionFactory 。從 applicationContext .xml 文件中調(diào)用這些行:

    -------------------------------------------------------------------------------

    < bean?id = " eventDao " ? class = " com.manning.hq.ch07.EventSpringDao>
    ??? < property?name = " sessionFactory " >
    ??? ??? < ref?bean = " factory " ? />
    ??? </ property >
    </ bean >

    ------------------------------------------------------------------

    這是調(diào)用 setSessionFactory () 的片斷,通過我們配置的 SessionFactory ,我們叫它為工廠。你所看到的 AbstractSpringDao 是由 AbstractDao 進(jìn)化而來,你可以從 find() 方法中完整的除去大多數(shù)資源管理代碼。 HibernateTemplate HibernateDaoSupport 替代了被控制的一切。

    ?

    創(chuàng)建注冊(cè)( Creating a registry )

    我們最終是為了將所有集中到一起并創(chuàng)建中心的注冊(cè),開發(fā)者能夠使用它直接獲得參數(shù)給 DAO SessionFactory 。通過單一的類, CalendarRegistry ,你能確保將來開發(fā)有一個(gè)顯示的,單一的,強(qiáng)壯類型的類來使用,不需要知道類的詳細(xì)內(nèi)部機(jī)制。 Figure 7.3 顯示了怎樣將所有集中到一起。

    使用 Spring ,你獲得了配置的好處,允許你輕松的交換數(shù)據(jù)資源,數(shù)據(jù)庫和添加新的對(duì)象成員。 Listing7.5 就是 CalendarRegistry

    springdao3.JPG

    ?

    Figure 7.3 CalendarRegistry 圖表,獲得參數(shù)到 EventDao

    ?

    Listing 7.5 CalendarRegistry , 組織 Dao 的中心的類

    -------------------------------------------------------------------------------------------------------------------------

    package ?com.manning.hq.ch07;

    import ?org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import ?org.hibernate.SessionFactory;

    public ? class ?CalendarRegistry?{
    ??? private ? static ?ApplicationContext?ctx;
    ??? static ?{
    ??? ??? ctx?
    = ? new ?ClassPathXmlApplicationContext( " applicationContext.xml " );
    ??? }
    ??? private ?CalendarRegistry()?{}
    ??? public ? static ?SessionFactory?getSessionFactory()?{
    ??? ??? return ?(SessionFactory)?ctx.getBean( " factory " ,?SessionFactory. class );
    ??? }
    ??? public ? static ?EventSpringDao?getEventDao()?{
    ??? ??? return ?(EventSpringDao)ctx.getBean( " eventDao " ,?EventSpringDao. class );
    ??? }
    }

    -------------------------------------------------------------------------------------------------------------------------

    正如你所見, CalendarRegistry 是單例模式,但是因?yàn)樗澈笫?/span> Spring ,你能夠輕松的實(shí)現(xiàn)底層的交換。它從 classpath 中裝載單一的靜態(tài)的 ApplicationContext ,然后使用它獲取參數(shù)。現(xiàn)在客戶端對(duì)象能夠在項(xiàng)目中任何地方獲得參數(shù)給 EventDao ,不需要知道關(guān)于 Spring 做了什么。

    -------------------------------------------------------------------------------------------------------------------------

    EventSpringDao?eventDao? = ?CalendarRegistry.getEventDao();
    eventDao.saveOrUpdate(event);

    --------------------------------------------------------------------------------------------

    ?

    更多的 Spring 工具

    就像你所見,使用 Spring 能夠最大限度的簡(jiǎn)化 Hibernate 的資源管理代碼。我們顯示了兩個(gè)你能夠使用的包含的級(jí)別。 HibernateTemplate 能夠被嵌入你的 DAO 中,或者使用 Spring 的輕量級(jí)容器去管理 DAO

    ??? Spring is a fairly straightforward framework, but we haven’t scratched the surface of what it can do here. Spring 還算一個(gè)直接的框架,但我們沒有就它能在這做什么過多的糾纏) Spring 也支持事務(wù) API 管理框架, AOP 框架,一個(gè) RuntimeException 框架,能夠攔截?cái)?shù)據(jù)庫發(fā)出的大多數(shù)遲鈍的 SQLException ,將它轉(zhuǎn)變成更顯而易見和包羅萬象的 exception 。更多的信息,請(qǐng)查看實(shí)在又全面的 Spring 文檔。

    ?

    7.5  總結(jié)

    這一章的焦點(diǎn)在于提高組織你的應(yīng)用程序代碼。我們集中了 HQL ,使用了 DAO 模式。我們通過加入其它的模式更提高了初始實(shí)現(xiàn),層的父型,它允許增加更多的DAO,不需要復(fù)制過多的代碼到項(xiàng)目中新添加的對(duì)象成員。

    ??? 這一章也探索了怎樣使用 Spring ,另一個(gè)流行的開源項(xiàng)目,管理 Hibernate 需要的 boilerplate (樣板)資源管理代碼。 Spring 提供了標(biāo)題選項(xiàng), HibernateTemplate pluggable ApplicationContext 。增加一個(gè) CalendarRegistry , 它提供了方法使用 Spring 獲得項(xiàng)目中的參數(shù),不再需要去包含一個(gè)“單塊集成電路”了。

    ?

    1 Hibernate 如此優(yōu)秀,為什么還要用別的?在現(xiàn)實(shí)中,轉(zhuǎn)變 ORM 實(shí)現(xiàn)并不是微不足道的, DAO 是容易產(chǎn)生漏洞的,提取那樣做的話就會(huì)有問題,將不能從應(yīng)用程序中完全隱藏 Hibernate 。( DAOs are leaky enough abstractions that doing so probably won’t completely hide Hibernate from the application. )。 因此不需要放太多的精力去密封 DAO 層,在以后為了可能的某種目的要轉(zhuǎn)變 ORM 實(shí)現(xiàn)。

    ?

    2 選自 Patterns of Enterprise Application Architecture , 作者: Martin Fowler(Addision-Wesley 專家, 2003 )

    ?

    3 選自在線文章“ Data Access with Spring Framework ”,作者: Juergen Hoeller 2003 7 月; http://hibernate.bluemars.net/110.html

    posted on 2005-12-21 22:21 千山鳥飛絕 閱讀(10516) 評(píng)論(6)  編輯  收藏 所屬分類: Hibernate

    FeedBack:
    # re: 用spring組織DAO
    2005-12-23 15:40 | xmlspy
    在這一點(diǎn)上,你將通過組合使用hibernate.cfg.xml文件(declaratively(公告的))和一些活躍的(programmatic)標(biāo)題,如HibernateFactory來配置Hibernate。Spring提供了另外一個(gè)選擇去整體declaratively(公告的)配置Hibernate。使用Spring的最大好處就是你能夠減少(programmatic)標(biāo)題配置需要的元素。

    -----------------
    翻譯得很變態(tài) :(

    declaratively ----聲明性的

    一些活躍的(programmatic)---- 使用靈活的編程方式

    上面兩個(gè)是相對(duì)應(yīng)的:
    聲明性的(指用配置文件) -- 編程方式的、硬編碼的(指寫java代碼)
      回復(fù)  更多評(píng)論
      
    # re: 用spring組織DAO
    2005-12-27 22:34 | 千山鳥飛絕
    謝謝xmlspy的指正  回復(fù)  更多評(píng)論
      
    # re: 用spring組織DAO
    2006-03-11 17:24 | skdk
    很通俗易懂的文章,在網(wǎng)上搜索了好久關(guān)于Spring DAO 的話題,這篇是我看到最好的, 比較全面的,比較清晰的一篇文章,希望,,在多發(fā),為我們初學(xué)Spring 的,提供一個(gè)良好的平臺(tái),謝謝!!
      回復(fù)  更多評(píng)論
      
    # re: 用spring組織DAO
    2007-05-20 19:40 | zhou
    樓主寫得不錯(cuò),樓主說的開發(fā)模式,我一直用,哈哈,有空大家研究一下  回復(fù)  更多評(píng)論
      
    # re: 用spring組織DAO
    2007-08-24 10:15 | chelson
    這本書名叫什么? 感覺作者的寫作思維相當(dāng)流暢, 讀起來一個(gè)字---爽
    refactor---------------重構(gòu)  回復(fù)  更多評(píng)論
      
    # re: 用spring組織DAO
    2007-08-24 16:39 | 千山鳥飛絕
    @chelson
    這本書叫做hibernate quickly,現(xiàn)在有中文版賣,售價(jià)也不高。

    適合hibernate入門時(shí)使用。  回復(fù)  更多評(píng)論
      

    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    正在閱讀:



    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    常用鏈接

    留言簿(35)

    隨筆檔案

    文章分類

    文章檔案

    好友的blog

    我的其他blog

    老婆的Blog

    搜索

    •  

    積分與排名

    • 積分 - 775160
    • 排名 - 56

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    主站蜘蛛池模板: 无人影院手机版在线观看免费| 亚洲一区精彩视频| 免费毛片a线观看| 情人伊人久久综合亚洲| 两性色午夜视频免费播放| a级亚洲片精品久久久久久久| 一级成人毛片免费观看| xvideos亚洲永久网址| 一区二区免费国产在线观看| 亚洲成av人片在线观看天堂无码| 视频一区二区三区免费观看| gogo全球高清大胆亚洲| 一级成人生活片免费看| 国产综合亚洲专区在线| 99精品免费视品| 亚洲精品人成在线观看| 亚洲一区免费视频| 亚洲成a人片在线看| 免费羞羞视频网站| 曰批全过程免费视频观看免费软件| 亚洲国产精品第一区二区三区| 国产成人高清精品免费观看| 亚洲国产精品一区二区第一页| 无码A级毛片免费视频内谢| 亚洲视频一区网站| 无码人妻久久一区二区三区免费丨| 亚洲一区二区三区丝袜| 四虎永久在线精品免费影视 | 丁香婷婷亚洲六月综合色| 猫咪社区免费资源在线观看 | 无码成A毛片免费| 91亚洲国产成人久久精品| 在线观看免费a∨网站| 特级毛片aaaa级毛片免费| 自拍偷自拍亚洲精品第1页| 无码囯产精品一区二区免费| 亚洲国产精品日韩在线| 日本媚薬痉挛在线观看免费| 国产美女视频免费观看的网站| 亚洲AV本道一区二区三区四区| 免费A级毛片无码无遮挡内射|