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

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

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

    posts - 32, comments - 153, trackbacks - 0, articles - 0
      BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

    Spring 與Hibernate的延遲加載和Dao模式 [翻譯]

    Posted on 2006-11-27 20:03 Zou Ang 閱讀(2165) 評論(2)  編輯  收藏 所屬分類:

    原帖地址:

    http://www.jroller.com/page/kbaum?entry=orm_lazy_initialization_with_dao

    Thursday July 08, 2004
    Spring Hibernate 的延遲加載和 Dao 模式

    Hibernate
    與延遲加載:

    Hibernate 對象關(guān)系映射提供延遲的與非延遲的對象初始化。非延遲加載在讀取一個(gè)對象的時(shí)候會將與這個(gè)對象所有相關(guān)的其他對象一起讀取出來。這有時(shí)會導(dǎo)致成百的(如果不是成千的話) select 語句在讀取對象的時(shí)候執(zhí)行。這個(gè)問題有時(shí)出現(xiàn)在使用雙向關(guān)系的時(shí)候,經(jīng)常會導(dǎo)致整個(gè)數(shù)據(jù)庫都在初始化的階段被讀出來了。當(dāng)然,你可以不厭其煩地檢查每一個(gè)對象與其他對象的關(guān)系,并把那些最昂貴的刪除,但是到最后,我們可能會因此失去了本想在 ORM 工具中獲得的便利。


    一個(gè)明顯的解決方法是使用 Hibernate 提供的延遲加載機(jī)制。這種初始化策略只在一個(gè)對象調(diào)用它的一對多或多對多關(guān)系時(shí)才將關(guān)系對象讀取出來。這個(gè)過程對開發(fā)者來說是透明的,而且只進(jìn)行了很少的數(shù)據(jù)庫操作請求,因此會得到比較明顯的性能提升。這項(xiàng)技術(shù)的一個(gè)缺陷是延遲加載技術(shù)要求一個(gè) Hibernate 會話要在對象使用的時(shí)候一直開著。這會成為通過使用 DAO 模式將持久層抽象出來時(shí)的一個(gè)主要問題。為了將持久化機(jī)制完全地抽象出來,所有的數(shù)據(jù)庫邏輯,包括打開或關(guān)閉會話,都不能在應(yīng)用層出現(xiàn)。最常見的是,一些實(shí)現(xiàn)了簡單接口的 DAO 實(shí)現(xiàn)類將數(shù)據(jù)庫邏輯完全封裝起來了。一種快速但是笨拙的解決方法是放棄 DAO 模式,將數(shù)據(jù)庫連接邏輯加到應(yīng)用層中來。這可能對一些小的應(yīng)用程序有效,但是在大的系統(tǒng)中,這是一個(gè)嚴(yán)重的設(shè)計(jì)缺陷,妨礙了系統(tǒng)的可擴(kuò)展性。

    Web 層進(jìn)行延遲加載

    幸運(yùn)的是, Spring 框架為 Hibernate 延遲加載與 DAO 模式的整合提供了一種方便的解決方法。對那些不熟悉 Spring Hibernate 集成使用的人,我不會在這里討論過多的細(xì)節(jié),但是我建議你去了解 Hibernate Spring 集成的數(shù)據(jù)訪問。以一個(gè) Web 應(yīng)用為例, Spring 提供了 OpenSessionInViewFilter OpenSessionInViewInterceptor 。我們可以隨意選擇一個(gè)類來實(shí)現(xiàn)相同的功能。兩種方法唯一的不同就在于 interceptor Spring 容器中運(yùn)行并被配置在 web 應(yīng)用的上下文中,而 Filter Spring 之前運(yùn)行并被配置在 web.xml 中。不管用哪個(gè),他們都在請求將當(dāng)前會話與當(dāng)前(數(shù)據(jù)庫)線程綁定時(shí)打開 Hibernate 會話。一旦已綁定到線程,這個(gè)打開了的 Hibernate 會話可以在 DAO 實(shí)現(xiàn)類中透明地使用。這個(gè)會話會為延遲加載數(shù)據(jù)庫中值對象的視圖保持打開狀態(tài)。一旦這個(gè)邏輯視圖完成了, Hibernate 會話會在 Filter doFilter 方法或者 Interceptor postHandle 方法中被關(guān)閉。下面是每個(gè)組件的配置示例:

    ?


    Interceptor的配置:

    < beans > ?
    < bean? id ="urlMapping" ?
    class
    ="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping" > ?
    < property? name ="interceptors" > ?
    < list > ?
    < ref? bean ="openSessionInViewInterceptor" /> ?
    </ list > ?
    </ property > ?
    < property? name ="mappings" > ?
    ?
    </ bean > ?
    ?
    < bean? name ="openSessionInViewInterceptor" ?
    class
    ="org.springframework.orm.hibernate.support.OpenSessionInViewInterceptor" > ?
    < property? name ="sessionFactory" >< ref? bean ="sessionFactory" /></ property > ?
    </ bean > ?
    </ beans > ?


    Filter的配置

    < web-app > ?
    ?
    < filter > ?
    < filter-name > hibernateFilter </ filter-name > ?
    < filter-class > ?
    org.springframework.orm.hibernate.support.OpenSessionInViewFilter?
    </ filter-class > ?
    </ filter > ?
    ?
    < filter-mapping > ?
    < filter-name > hibernateFilter </ filter-name > ?
    < url-pattern > *.?spring? </ url-pattern > ?
    </ filter-mapping > ?
    ?
    </ web-app > ?


    實(shí)現(xiàn) Hibernate Dao 接口來使用打開的會話是很容易的。事實(shí)上,如果你已經(jīng)使用了 Spring 框架來實(shí)現(xiàn)你的 Hibernate Dao, 很可能你不需要改變?nèi)魏螙|西。方便的 HibernateTemplate 公用組件使訪問數(shù)據(jù)庫變成小菜一碟,而 DAO 接口只有通過這個(gè)組件才可以訪問到數(shù)據(jù)庫。下面是一個(gè)示例的 DAO

    public ? class ?HibernateProductDAO? extends ?HibernateDaoSupport? implements ?ProductDAO? {?

    public ?Product?getProduct(Integer?productId)? {?
    return ?(Product)getHibernateTemplate().load(Product. class ,?productId);?
    }
    ?

    public ?Integer?saveProduct(Product?product)? {?
    return ?(Integer)?getHibernateTemplate().save(product);?
    }
    ?

    public ? void ?updateProduct(Product?product)? {?
    getHibernateTemplate().update(product);?
    }
    ?
    }
    ?

    ?

    在業(yè)務(wù)邏輯層中使用延遲加載

    即使在視圖外面, Spring 框架也通過使用 AOP?攔截器 HibernateInterceptor 來使得延遲加載變得很容易實(shí)現(xiàn)。這個(gè) Hibernate 攔截器 透明地將調(diào)用配置在 Spring 應(yīng)用程序上下文中的業(yè)務(wù)對象中方法的請求攔截下來,在調(diào)用方法之前打開一個(gè) Hibernate 會話,然后在方法執(zhí)行完之后將會話關(guān)閉。讓我們來看一個(gè)簡單的例子,假設(shè)我們有一個(gè)接口 BussinessObject

    public ??? interface ??BusinessObject??? {?
    ?
    public ??? void ??doSomethingThatInvolvesDaos();?
    }
    ?

    類BusinessObjectImpl實(shí)現(xiàn)了BusinessObject接口:

    public ??? class ??BusinessObjectImpl?? implements ??BusinessObject??? {?
    ?
    public ??? void ??doSomethingThatInvolvesDaos()??? {?
    ?
    // ??lots?of?logic?that?calls?
    ?
    // ??DAO?classes?Which?access?
    ?
    // ??data?objects?lazily??
    ?}
    ??
    }
    ??


    通過在Spring應(yīng)用程序上下文中的一些配置,我們可以讓將調(diào)用BusinessObject的方法攔截下來,再令它的方法支持延遲加載。看看下面的一個(gè)程序片段:


    < beans > ?
    < bean? id ="hibernateInterceptor" ?class ="org.springframework.orm.hibernate.HibernateInterceptor" > ?
    < property? name ="sessionFactory" > ?
    < ref? bean ="sessionFactory" /> ?
    </ property > ?
    </ bean > ?
    < bean? id ="businessObjectTarget" ?class ="com.acompany.BusinessObjectImpl" > ?
    < property? name ="someDAO" >< ref? bean ="someDAO" /></ property > ?
    </ bean > ?
    < bean? id ="businessObject" ?class ="org.springframework.aop.framework.ProxyFactoryBean" > ?
    < property? name ="target" >< ref? bean ="businessObjectTarget" /></ property > ?
    < property? name ="proxyInterfaces" > ?
    < value > com.acompany.BusinessObject </ value > ?
    </ property > ?
    < property? name ="interceptorNames" > ?
    < list > ?
    < value > hibernateInterceptor </ value > ?
    </ list > ?
    </ property > ?
    </ bean > ?
    </ beans >


    當(dāng) businessObject 被調(diào)用的時(shí)候, HibernateInterceptor 打開一個(gè) Hibernate 會話,并將調(diào)用請求傳遞給 BusinessObjectImpl 對象。當(dāng) BusinessObjectImpl 執(zhí)行完成后, HibernateInterceptor 透明地關(guān)閉了會話。應(yīng)用層的代碼不用了解任何持久層邏輯,還是實(shí)現(xiàn)了延遲加載。


    在單元測試中測試延遲加載

    最后,我們需要用 J-Unit 來測試我們的延遲加載程序。我們可以輕易地通過重寫 TestCase 類中的 setUp tearDown 方法來實(shí)現(xiàn)這個(gè)要求。我比較喜歡用這個(gè)方便的抽象類作為我所有測試類的基類。

    public ? abstract ? class ?MyLazyTestCase? extends ?TestCase? {?

    private ?SessionFactory?sessionFactory;?
    private ?Session?session;?

    public ? void ?setUp()? throws ?Exception? {?
    super .setUp();?
    SessionFactory?sessionFactory?
    = ?(SessionFactory)?getBean( " sessionFactory " );?
    session?
    = ?SessionFactoryUtils.getSession(sessionFactory,? true );?
    Session?s?
    = ?sessionFactory.openSession();?
    TransactionSynchronizationManager.bindResource(sessionFactory,?
    new ?SessionHolder(s));?

    }
    ?

    protected ?Object?getBean(String?beanName)? {?
    // Code?to?get?objects?from?Spring?application?context?
    }
    ?

    public ? void ?tearDown()? throws ?Exception? {?
    super .tearDown();?
    SessionHolder?holder?
    = ?(SessionHolder)?TransactionSynchronizationManager.getResource(sessionFactory);?
    Session?s?
    = ?holder.getSession();?
    s.flush();?
    TransactionSynchronizationManager.unbindResource(sessionFactory);?
    SessionFactoryUtils.closeSessionIfNecessary(s,?sessionFactory);?
    }
    ?
    }
    ?

    評論

    # re: Spring 與Hibernate的延遲加載和Dao模式 [翻譯]  回復(fù)  更多評論   

    2006-11-30 10:04 by 開源狂人[匿名]
    汗顏

    # re: Spring 與Hibernate的延遲加載和Dao模式 [翻譯]  回復(fù)  更多評論   

    2008-07-03 23:36 by Yvon
    我正在找這方面的資料,謝謝博主的分享
    主站蜘蛛池模板: 一个人免费观看在线视频www| 在线观看亚洲专区| 亚洲人成网址在线观看| 亚洲线精品一区二区三区 | 香蕉97碰碰视频免费| 亚洲国产精品网站在线播放| 亚洲精品美女网站| 亚洲中文字幕一区精品自拍| 亚洲中文无码mv| 亚洲av第一网站久章草| 国产成人精品久久亚洲高清不卡 | 亚洲AV人无码综合在线观看| 久久精品国产精品亚洲艾草网 | 久久久久亚洲AV无码专区网站 | 国产成人在线免费观看| 天堂亚洲免费视频| 亚洲日韩国产精品第一页一区| 亚洲啪啪AV无码片| 午夜影视日本亚洲欧洲精品一区| 91亚洲国产成人精品下载| 亚洲综合男人的天堂色婷婷| 亚洲日韩国产精品乱-久| 亚洲国产精品无码久久98 | 亚洲熟女精品中文字幕| 亚洲av永久无码精品网址 | 亚洲色欲www综合网| 亚洲伊人久久大香线蕉影院| 亚洲中文无码mv| 中美日韩在线网免费毛片视频| 精品熟女少妇aⅴ免费久久| 精品一区二区三区免费| 久草视频免费在线观看| 免费观看大片毛片| 亚洲综合另类小说色区色噜噜| 亚洲AV无码精品无码麻豆| 亚洲一级高清在线中文字幕| 国产成人精品日本亚洲语音| 十八禁在线观看视频播放免费| 免费观看黄色的网站| 免费一级做a爰片久久毛片潮喷| 亚洲精品无码专区在线在线播放 |