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

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

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

    Dict.CN 在線詞典, 英語學習, 在線翻譯

    都市淘沙者

    荔枝FM Everyone can be host

    統計

    留言簿(23)

    積分與排名

    優秀學習網站

    友情連接

    閱讀排行榜

    評論排行榜

    Hibernate與緩存技術

    對于Hibernate這類ORM而言,緩存顯的尤為重要,它是持久層性能提升的關鍵.簡單來講Hibernate就是對JDBC進行封裝,以實現內部狀態的管理,OR關系的映射等,但隨之帶來的就是數據訪問效率的降低,和性能的下降,而緩存就是彌補這一缺點的重要方法.

        緩存就是數據庫數據在內存中的臨時容器,包括數據庫數據在內存中的臨時拷貝,它位于數據庫與數據庫訪問層中間.ORM在查詢數據時首先會根據自身的緩存管理策略,在緩存中查找相關數據,如發現所需的數據,則直接將此數據作為結果加以利用,從而避免了數據庫調用性能的開銷.而相對內存操作而言,數據庫調用是一個代價高昂的過程.

        一般來講ORM中的緩存分為以下幾類:

            
    1.事務級緩存:即在當前事務范圍內的數據緩存.就Hibernate來講,事務級緩存是基于Session的生命周期實現的,每個Session內部會存在一個數據緩存,它隨著Session的創建而存在,隨著Session的銷毀而滅亡,因此也稱為Session Level Cache.

            
    2.應用級緩存:即在某個應用中或應用中某個獨立數據庫訪問子集中的共享緩存,此緩存可由多個事務共享(數據庫事務或應用事務),事務之間的緩存共享策略與應用的事務隔離機制密切相關.在Hibernate中,應用級緩存由SessionFactory實現,所有由一個SessionFactory創建的Session實例共享此緩存,因此也稱為SessionFactory Level Cache.

            
    3.分布式緩存:即在多個應用實例,多個JVM間共享的緩存策略.分布式緩存由多個應用級緩存實例組成,通過某種遠程機制(RMI,JMS)實現各個緩存實例間的數據同步,任何一個實例的數據修改,將導致整個集群間的數據狀態同步.

        Hibernate數據緩存:

            
    1.內部緩存(Session Level Cache也稱一級緩存):

            舉例說明:

    java 代碼
    public class Test {    
       
          
    public void get(){     
       
                Session session 
    = HibernateSessionFactory.getSession();    
                TUser t 
    = (TUser)session.get("hibernate.TUser"2);    
                System.out.println(t.getName());    
                session.close();    
                }
        
       
    }
        
       

                 進行測試:在控制臺打印出一條SQL語句:Hibernate: select tuser0_.id as id0_0_, tuser0_.name as name0_0_, tuser0_.sex as sex0_0_ from test.t_user tuser0_ where tuser0_.id
    =? 說明進行了一次數據庫的調用.

          代碼更改如下:

    public class Test {    
         
          
    public void get(){    
       
                Session session 
    = HibernateSessionFactory.getSession();    
                TUser t 
    = (TUser)session.get("hibernate.TUser"2);    
                System.out.println(t.getName());    
                TUser tt 
    = (TUser)session.get("hibernate.TUser"2);    
                System.out.println(tt.getName());    
                session.close();    
       
          }
        
       
    }
        
       

           再進行測試:進行了兩次查詢,控制臺仍然只打出一條SQL語句:Hibernate: select tuser0_.id as id0_0_, tuser0_.name as name0_0_, tuser0_.sex as sex0_0_ from test.t_user tuser0_ where tuser0_.id
    =?  說明還是只進行了一次數據庫的調用.

           再將代碼更改如下:

    public class Test {    
         
          
    public void get(){     
       
                Session session 
    = HibernateSessionFactory.getSession();    
                TUser t 
    = (TUser)session.get("hibernate.TUser"2);    
                System.out.println(t.getName());    
                session.close();    
                Session session1 
    = HibernateSessionFactory.getSession();    
                TUser tt 
    = (TUser)session1.get("hibernate.TUser"2);    
                System.out.println(tt.getName());    
                session1.close();    
       
          }
        
       
    }
        

           繼續測試:進行兩次查詢控制臺打印兩條SQL語句:Hibernate: select tuser0_.id as id0_0_, tuser0_.name as name0_0_, tuser0_.sex as sex0_0_ from test.t_user tuser0_ where tuser0_.id
    =?
    Hibernate: select tuser0_.id as id0_0_, tuser0_.name as name0_0_, tuser0_.sex as sex0_0_ from test.t_user tuser0_ where tuser0_.id
    =?

          結論:Hibernate進行查詢時總是先在緩存中進行查詢,如緩存中沒有所需數據才進行數據庫的查詢.Hibernate的內部緩存是基于Session的生命周期的,也就是說存在于每個Session內部,它隨著Session的創建而存在,隨著Session的銷毀而滅亡,內部緩存一般由Hibernate自動維護,不需要人為干預,當然我們也可以根據需要進行相應操作:Session.evict(Object)(將指定對象從內部緩存清除),Session.clear()(清空內部緩存).(如在兩次查詢間加入Session.clear()將會清空內部緩存,使得一個Sesion內部的兩次相同的查詢要對數據庫進行兩次操作).

          
    2.二級緩存:(有時稱為SessionFactory Level Cache)

          Hibernate本身并未提供二級緩存的產品化實現(只提供了一個基于HashTable的簡單緩存以供調試),這里我使用的是第三方緩存組件:EHcache.Hibernate的二級緩存實現需要進行以下配置(Hibernate3):

          首先在hibernate.cfg.xml內添加: 



    <property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>   
    <property name="hibernate.cache.use_query_cache">true</property>   

    然后在映射文件中添加:
    <cache usage="read-only"/>   

                測試上面代碼:控制臺輸出多了這樣一句[ WARN] (CacheFactory.java:
    43- read-only cache configured for mutable class: hibernate.TUser,二級緩存啟用成功!!       

    java 代碼
    public class Test {    
         
          
    public void executeQuery(){    
          
                List list 
    = new ArrayList();    
                Session session 
    = HibernateSessionFactory.getSession();    
                Query query 
    = session.createQuery("from TUser t");    
                query.setCacheable(
    true);//激活查詢緩存    
                list = query.list();    
                session.close();    
       
          }
        
          
    public void get(){    
       
                Session session 
    = HibernateSessionFactory.getSession();    
                TUser t 
    = (TUser)session.get("hibernate.TUser"2);    
                System.out.println(t.getName());    
                session.close();    
       
         }
        
       
    }
        

          測試:控制臺只輸出一條SQL語句:Hibernate: select tuser0_.id as id0_, tuser0_.name as name0_, tuser0_.sex as sex0_ from test.t_user tuser0_(即Query query 
    = session.createQuery("from TUser t")這句代碼所對應的SQL).  executeQuery()方法與get()方法使用的是不同的Session!!可是executeQuery()方法與get()方法只對數據庫進行了一次操作,這就是二級緩存在起作用了.   

          結論:Hibernate二級緩存是SessionFactory級的緩存,它允許多個Session間共享,使用時需要使用第三方的緩存組件,新版Hibernate將EHcache作為默認的二級緩存實現.

          緩存同步策略:緩存同步策略決定了數據對象在緩存中的存取規則,我們必須為每個實體類指定相應的緩存同步策略.Hibernate中提供了4種不同的緩存同步策略:(暫時只記個概念吧)

          
    1.read-only:只讀.對于不會發生改變的數據可使用(對數據只能查詢,其他的增刪改都會報錯不關是1或2緩存中).

          
    2.nonstrict-read-write:如果程序對并發訪問下的數據同步要求不嚴格,且數據更新頻率較低,采用本緩存同步策略可獲得較好性能.(不能在二級緩存進行增刪改都會報錯)

          
    3.read-write:嚴格的讀寫緩存.基于時間戳判定機制,實現了"read committed"事務隔離等級.用于對數據同步要求的情況,但不支持分布式緩存,實際應用中使用最多的緩存同步策略.(都可以比較常用的)

          
    4.transactional:事務型緩存,必須運行在JTA事務環境中.此緩存中,緩存的相關操作被添加到事務中(此緩存類似于一個內存數據庫),如事務失敗,則緩沖池的數據會一同回滾到事務的開始之前的狀態.事務型緩存實現了"Repeatable read"事務隔離等級,有效保證了數據的合法性,適應于對關鍵數據的緩存,Hibernate內置緩存中,只有JBossCache支持事務型緩存.
     
    Hibernate獲取數據的方式有不同的幾種,其與緩存結合使用的效果也不盡相同,而Hibernate中具體怎么使用緩存其實是我們很關心的一個問題,直接涉及到性能方面。
    緩存在Hibernate中主要有三個方面:一級緩存、二級緩存和查詢緩存;一級緩存在Hibernate中對應的即為session范圍的緩存,也就是當 session關閉時緩存即被清除,一級緩存在Hibernate中是不可配置的部分;二級緩存在Hibernate中對應的即為 SessionFactory范圍的緩存,通常來講SessionFactory的生命周期和應用的生命周期相同,所以可以看成是進程緩存或集群緩存,二級緩存在Hibernate中是可以配置的,可以通過class
    -cache配置類粒度級別的緩存(class-cache在class中數據發生任何變化的情況下自動更新),同時也可通過collection-cache配置集合粒度級別的緩存(collection-cache僅在 collection中增加了元素或者刪除了元素的情況下才自動更新,也就是當collection中元素發生值的變化的情況下它是不會自動更新的),緩存自然會帶來并發的訪問問題,這個時候相應的就要根據應用來設置緩存所采用的事務隔離級別,和數據庫的事務隔離級別概念基本一樣,沒什么多介紹的, ^_^;查詢緩存在Hibernate同樣是可配置的,默認是關閉的,可以通過設置cache.use_ query_cache為true來打開查詢緩存。根據緩存的通常實現策略,我們可以來理解Hibernate的這三種緩存,緩存的實現通過是通過key/value的Map方式來實現,在 Hibernate的一級、二級和查詢緩存也同樣如此,一級、二級緩存使用的key均為po的主鍵ID,value即為po實例對象,查詢緩存使用的則為查詢的條件、查詢的參數、查詢的頁數,value有兩種情況,如果采用的是select po.property這樣的方式那么value為整個結果集,如采用的是from這樣的方式那么value為獲取的結果集中各po對象的主鍵ID,這樣的作用很明顯,節省內存,^_^
    簡單介紹完Hibernate的緩存后,再結合Hibernate的獲取數據方式來說明緩存的具體使用方式,在Hibernate中獲取數據常用的方式主要有四種:Session.load、Session.get、Query.list、Query.iterator。
    1、Session.load
          在執行session.load時,Hibernate首先從當前session的一級緩存中獲取id對應的值,在獲取不到的情況下,將根據該對象是否配置了二級緩存來做相應的處理,如配置了二級緩存,則從二級緩存中獲取id對應的值,如仍然獲取不到則還需要根據是否配置了延遲加載來決定如何執行,如未配置延遲加載則從數據庫中直接獲取,在從數據庫獲取到數據的情況下,Hibernate會相應的填充一級緩存和二級緩存,如配置了延遲加載則直接返回一個代理類,只有在觸發代理類的調用時才進行數據庫查詢的操作。
          在這樣的情況下我們就可以看到,在session一直打開的情況下,要注意在適當的時候對一級緩存進行刷新操作,通常是在該對象具有單向關聯維護的時候,在Hibernate中可以使用象session.clear、session.evict的方式來強制刷新一級緩存。
          二級緩存則在數據發生任何變化(新增、更新、刪除)的情況下都會自動的被更新。
    2、Session.get
          在執行Session.get時,和Session.load不同的就是在當從緩存中獲取不到時,直接從數據庫中獲取id對應的值。
    3、Query.list
          在執行Query.list時,Hibernate的做法是首先檢查是否配置了查詢緩存,如配置了則從查詢緩存中查找key為查詢語句
    +查詢參數+分頁條件的值,如獲取不到則從數據庫中進行獲取,從數據庫獲取到后Hibernate將會相應的填充一級、二級和查詢緩存,如獲取到的為直接的結果集,則直接返回,如獲取到的為一堆id的值,則再根據id獲取相應的值(Session.load),最后形成結果集返回,可以看到,在這樣的情況下,list也是有可能造成N次的查詢的。
          查詢緩存在數據發生任何變化的情況下都會被自動的清空。
    4、Query.iterator
          在執行Query.iterator時,和Query.list的不同的在于從數據庫獲取的處理上,Query.iterator向數據庫發起的是 select id from這樣的語句,也就是它是先獲取符合查詢條件的id,之后在進行iterator.next調用時才再次發起session.load的調用獲取實際的數據。
          可見,在擁有二級緩存并且查詢參數多變的情況下,Query.iterator會比Query.list更為高效。

    這四種獲取數據的方式都各有適用的場合,要根據實際情況做相應的決定,
    ^_^,最好的方式無疑就是打開show_sql選項看看執行的情況來做分析,系統結構上只用保證這種調整是容易實現的就好了,在cache這個方面的調整自然是非常的容易,只需要調整配置文件里的設置,而查詢的方式則可對外部進行屏蔽,這樣要根據實際情況調整也非常容易。
    1<hibernate-configuration>
     
        
    <session-factory>
           
    <property name="connection.username">sa</property>
           
    <property name="connection.url">
               jdbc:microsoft:sqlserver:
    //localhost:1433;databasename=pubs
           </property>
           
    <property name="dialect">
               org.hibernate.dialect.SQLServerDialect
           
    </property>
           
    <property name="myeclipse.connection.profile">conn</property>
           
    <property name="connection.driver_class">
               com.microsoft.jdbc.sqlserver.SQLServerDriver
           
    </property>
           
    <property name="show_sql">true</property>
           
    <!-- 添加2級緩存開始 -->
           
    <property name="cache.provider_class">
               org.hibernate.cache.EhCacheProvider
           
    </property>
           
    <property name="hibernate.cache.use_query_cache">true</property>
           
    <!-- 結束 -->
           
    <mapping resource="org/jw/po/Users.hbm.xml" />
     
        
    </session-factory>
     
    </hibernate-configuration>
    2
    <hibernate-mapping>
        
    <class name="org.jw.po.Users" table="users" schema="dbo" catalog="pubs">
            
    <!--配置-->
            
    <cache usage="read-only"></cache>
            
    <id name="sid" type="java.lang.Integer">
                
    <column name="sid" />
                
    <generator class="identity" />
            
    </id>
            
    <property name="sname" type="java.lang.String">
                
    <column name="sname" length="20" not-null="true" />
            
    </property>
        
    </class>
    </hibernate-mapping>
     

    posted on 2008-10-09 10:38 都市淘沙者 閱讀(540) 評論(0)  編輯  收藏 所屬分類: Hibernate/ORM

    主站蜘蛛池模板: 亚洲视频在线观看| 亚洲综合伊人久久大杳蕉| 国产真实伦在线视频免费观看| 日韩黄色免费观看| 亚洲国产精品丝袜在线观看| 亚洲自偷自偷在线制服| 亚洲国产一区在线| 国产成人亚洲精品91专区手机| 99久久国产精品免费一区二区 | 亚洲视频在线观看免费视频| 无码一区二区三区AV免费| 日韩精品无码永久免费网站| 亚洲精品视频在线播放| 日韩免费观看视频| 国产精品免费AV片在线观看| 亚洲精品无码专区| 亚洲国产精品一区| 亚洲国产成人久久笫一页| 最近2019免费中文字幕6| 免费看美女午夜大片| 亚洲精品国产免费| 亚洲色偷偷综合亚洲AV伊人| 中字幕视频在线永久在线观看免费| 九九热久久免费视频| 爱情岛论坛免费视频| 91亚洲自偷在线观看国产馆| 亚洲第一页在线播放| 久久亚洲综合色一区二区三区 | 日韩免费在线观看| 免费无码中文字幕A级毛片| 亚洲理论在线观看| 亚洲色无码专区在线观看| 亚洲国产AV一区二区三区四区| 久久永久免费人妻精品下载| a毛片基地免费全部视频| 久久免费看少妇高潮V片特黄| 成人免费视频试看120秒| 亚洲色大成网站www永久一区| 亚洲自国产拍揄拍| a级毛片无码免费真人久久| 成熟女人牲交片免费观看视频|