《深入淺出Hibernate》緩存,實體生命週期,事務處理

已讀到《Hibernate高級特性》一章,看china-pub和第2書店上的書評,都說這纔是本書的精華所在,仔細研讀中。。。概念開始比較多了,也澄清了一些過去模模糊糊的概念,比如實體對象的3種狀態,比如PO,VO之爭,比如Hibernate的二級緩存是怎麼回事。全章分爲兩部分,第一部分Hibernate的持久化操作,包括以下內容:

  1. 實體對象的生命週期。在Hibernate中,實體對象只能爲3種狀態:Transient,Persistent,Detached。Transient即實體對象是自由的,與數據庫中的記錄無關。Persistent即實體對象處於Hibernate框架的管理之中,其變更將由hibernate更新到數據庫中。Detached(遊離),處於Persistent狀態的對象在Session關閉之後,此對象就處於Detached狀態。比如:
                    TUser user=new TUser();    
                    user.setName("dennis");   //user此時爲Transient狀態        
                    Transaction tran=session.beginTransaction();

                              session.save(user);           //user開始處於Persistent狀態           
                              tx.commint();

                              session.close();             //session關閉之後,user處於detached狀態

               那麼,Detached狀態與Transient狀態的區別在哪?區別就在於Detached可以再次與session相關聯而進 入Persistent狀態。Transient的對象與數據庫記錄缺乏聯繫,比如沒有主鍵,而Detached對象是與數據庫的記錄相聯繫的,在庫中有相應的記錄(通過主鍵唯一確定)。我們可以人工製造Detached對象。由此可引出VO和PO的概念,我們從“實體是否納入Hibernate實體管理器的管理的”的觀點出發,把非管理的實體對象(Transient,Detached)稱爲VO(Value Object),把被管理的實體對象稱爲PO(Persistence Object)。由PO和VO的概念引出一個設計上的考量,如在傳統的MVC架構中,PO是否被允許傳播到其他層,因爲PO的更新將最終被影射到數據庫,所以如果PO在其他層遭到了變動,可能對Model層造成意想不到的破壞,一般是通過構造一個DTO對象來避免此情況(儘管這被rod狂批了一頓)。此方面的技術有commons項目的BeanUtils和dozer.

         2.實體對象的識別:此節主要討論瞭如何撰寫實體對象的equals()和hashCode()方法。從兩種角度出發,站在數據庫的角度,我們應該認爲在一庫表結構中,主鍵可以唯一確定一條記錄,那麼,擁有同樣主鍵值的對象,則認爲他們等同。而從業務邏輯的角度出發,我們可能認爲一個user對象的name相同,就認爲此兩個實體對象等價,需要根據特定領域中的邏輯規則。值對比,即在equals/hashcode方法中,對實體類的所有屬性的值進行對比,只需針對實體類的屬性進行處理,而不要涉及實體類所關聯的集合類的對比。Hibernate中的髒數據檢查是通過數據版本比對機制,書中給出了一個對象更新過程的UML序列圖。

         3。數據緩存。在ORM中,緩存一般分爲3個層次:                 
                A。事務級緩存,當前事務範圍內的緩存策略

                B。應用級,在某個應用中,或者應用中某個獨立訪問數據庫的子集中的共享緩存。

                C。分佈式緩存,在不同JVM中共享的緩存模式。

             Hibernate中的緩存分爲兩個層次:

              A。Session Level,內部緩存,通過session在內部維持一個Map數據類型維護當前Session中的所有有關PO的狀態。通常情況下由Hibernate自動維護,可通過Session.evict和Session.clear人工管理。

              B。SessionFactory Level,二級緩存。涵蓋了應用級和分佈式緩存。二級緩存將由從屬於本SessionFactory的所有Session實例共享。關於2級緩存的具體討論,在javaeye上有個很精彩的帖子。http://forum.javaeye.com/viewtopic.php?t=18904

         4。事務管理。首先介紹了概念,如ACID,事務管理隔離等級等。再解釋了Hibernate中的兩種事務管理類型:JDBC和JTA。在實際應用中可能更多的與spring集合,採用spring封裝的事務管理。如配置:

        <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

    <!--Base TransactionProxyed Service Bean-->
    <bean id="baseTxService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true">
        <property name="transactionManager" ref="transactionManager"/>
        <property name="proxyTargetClass" value="true"/>

        <property name="transactionAttributes">
            <props>
                <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
                <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
                <prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>
                <prop key="save*">PROPAGATION_REQUIRED</prop>
                <prop key="update*">PROPAGATION_REQUIRED</prop>
                <prop key="remove*">PROPAGATION_REQUIRED</prop>
            </props>
        </property>
        <property name="preInterceptors">
            <list>
                <ref bean="methodSecurityInterceptor"/>
            </list>
        </property>
    </bean>

要納入事務管理的bean,只要如此聲明:


    <bean id="bookManager" parent="baseTxService">
        <property name="target">
            <bean class="org.springside.bookstore.service.logic.BookManager"/>
        </property>
    </bean>

以上片段摘自SpringSide項目。

Hibernate支持兩種鎖機制,即通常所說的“悲觀鎖”與“樂觀鎖”。

A。悲觀鎖,指的是對數據被外界修改持保守態度,在整個數據處理過程中,把數據一直維持在鎖定狀態。一般都是通過調用數據庫的鎖機制實現,典型代碼如下:

String hqlstr="from TUser as user where user.name='dennis'";

Query query=session.createQuery(hqlstr);

Query.setLockModel("user",LockModel.UPGRADE);      //此句實現了加鎖

List list=Query.list();    //執行查詢。

常見鎖機制:LockModel.UPGRADE,LockModel.UPGRADE_NOWAIT(僅限oracle)。加鎖可通過Criteria,Session,Query的setLockModel方法實現。

B。樂觀鎖。悲觀鎖在大多數情況下依賴數據庫的鎖機制,保證最大限度的獨佔性,但對於長事務而言,隨之而來的是數據庫性能的大量開銷。因此纔有了樂觀鎖,與悲觀鎖不同,樂觀鎖其實並未給數據加鎖,它是通過數據版本記錄機制實現,只有提交的數據版號大於數據表當前數據版本號,纔給予更新,否則認爲是過期數據。一般是爲數據庫表增加一個"version"字段。配置如:

<class name="TUser" table="t_user" optimistic-lock="version">

<version column="version" name="version" type="java.lang.Integer"/>

optimistic-lock的值可以爲:none,version,dirty,all。官方推薦version實現的樂觀鎖機制。

 

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