Hibernate之一級緩存和二級緩存


1:Hibernate的一級緩存:

  1.1:使用一級緩存的目的是為了減少對數據庫的訪問次數,從而提升hibernate的執行效率;(當執行一次查詢操作的時候,執行第二次查詢操作,先檢查緩存中是否有數據,如果有數據就不查詢數據庫,直接從緩存中獲取數據);

   1.2:Hibernate中的一級緩存,也叫做session的緩存,它可以在session范圍內減少數據庫的訪問次數,只在session范圍內有效,session關閉,一級緩存失敗;

  1.3:一級緩存的特點,只在session范圍有效,作用時間短,效果不是特別明顯,在短時間內多次操作數據庫,效果比較明顯。

  1.4:當調用session的save/saveOrUpdate/get/load/list/iterator方法的時候,都會把對象放入session緩存中;

  1.5:session的緩存是由hibernate維護的,用戶不能操作緩存內容;如果想操作緩存內容,必須通過hibernate提供的evict/clear方法操作

  1.6:緩存相關的方法(在什么情況下使用上面方法呢?批量操作情況下使用,如Session.flush();先與數據庫同步,Session.clear();再清空一級緩存內容):

    session.flush();讓一級緩存與數據庫同步;

    session.evict();清空一級緩存中指定的對象;

    session.clear();清空一級緩存中所有的對象;

  1.7:面試題,不同的session是否會共享緩存數據?

      答:不會哦~~~

  1.8:list和iterator的區別?

    (1)list查詢:

      答: 一次性把所有的記錄都查詢出來了;會放入緩存,不會從緩存中取數據;

    (2)iterate(N+1次查詢):

      答: N表示所有的記錄總數,即會發送一條語句查詢所有的記錄的主鍵,這是第一條查詢語句,再根據每一個主鍵取數據庫查詢,這是根據第一次查詢的條數進行N次查詢操作;會放入緩存,也會從緩存中取出數據;


2:Hibernate的懶加載:

  2.1:懶加載概念:當用到數據的時候才向數據庫查詢,這就是hibernate的懶加載特性。

     使用懶加載的目的,是提高程序執行效率。

  2.2:查詢操作:get()方法/load()方法

    (1)get()方法,及時加載。及時查詢操作;只要調用get方法立刻向數據庫查詢。

    (2)load()方法,默認懶加載,即在使用數據的時候,才向數據庫發送查詢的sql語句。session關閉以后,不可以使用懶加載。

#懶加載默認為true,即為懶加載,可以改為非懶加載。即lazy="false"
#lazy="false" 關閉懶加載
#lazy="true"使用懶加載
#lazy="extra"在真正使用數據的時候才向數據庫發送查詢的sql語句。集合屬性懶加載的時候提升效率。如果調用集合的size()/isEmpty()方法只是統計,不真正查詢數據。
<class name="類名稱" table="數據表名稱" lazy="false"> ...... </class>

   2.3:懶加載異常:

    Session關閉后,不能使用懶加載數據,如果session關閉后,使用懶加載數據報錯如:

org.hibernate.LazyInitializationException: could not initialize proxy - no Session
    at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:167)
    at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:215)
    at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:190)
    at com.bie.lesson05.Dept_$$_javassist_1.getDeptName(Dept_$$_javassist_1.java)
    at com.bie.lesson05.ManyToManyTest.lazyTest(ManyToManyTest.java:241)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

    如何解決session關閉后不能使用懶加載加載數據的問題:

      方式一:可以先在關閉session之前使用一下數據,這樣關閉以后就可以使用此數據了。如Dept.getDeptName();

      方式二(推薦):強迫代理對象初始化操作:Hibernate.initialize(對象);

      方式三:關閉懶加載(lazy="false");

      方式四(推薦):在使用數據之后再關閉session;


 3:二級緩存:

Hibernate提供的緩存

有一級緩存、二級緩存。 目的是為了減少對數據庫的訪問次數,提升程序執行效率!

 

一級緩存:

基於Session的緩存,緩存內容只在當前session有效,session關閉,緩存內容失效!

特點:

作用范圍較小! 緩存的事件短。

緩存效果不明顯。

  3.1:二級緩存概述:

  二級緩存:

    Hibernate提供了基於應用程序級別的緩存即為二級緩存,可以跨多個session,即不同的session都可以訪問緩存數據。 這個緩存也叫二級緩存。

    Hibernate提供的二級緩存有默認的實現,且是一種可插配的緩存框架!如果用戶想用二級緩存,只需要在hibernate.cfg.xml中配置即可; 不想用,直接移除,不影響代碼。

    如果用戶覺得hibernate提供的框架框架不好用,自己可以換其他的緩存框架或自己實現緩存框架都可以。  

  3.2:查看hibernate.properties配置文件,二級緩存如何配置?

##########################

### Second-level Cache ###

##########################

#hibernate.cache.use_second_level_cache false【二級緩存默認不開啟,需要手動開啟】

#hibernate.cache.use_query_cache true      【開啟查詢緩存】

 
## choose a cache implementation 【二級緩存框架的實現】

 
#hibernate.cache.provider_class org.hibernate.cache.EhCacheProvider

#hibernate.cache.provider_class org.hibernate.cache.EmptyCacheProvider

hibernate.cache.provider_class org.hibernate.cache.HashtableCacheProvider 默認實現

#hibernate.cache.provider_class org.hibernate.cache.TreeCacheProvider

#hibernate.cache.provider_class org.hibernate.cache.OSCacheProvider

#hibernate.cache.provider_class org.hibernate.cache.SwarmCacheProvider

  3.3:二級緩存,使用步驟:

  1) 開啟二級緩存;

  2)指定緩存框架;

  3)指定那些類加入二級緩存;

  4)測試;

<!--****************** 【二級緩存配置】****************** -->
<!-- a.  開啟二級緩存 -->
<property name="hibernate.cache.use_second_level_cache">true</property>
<!-- b. 指定使用哪一個緩存框架(默認提供的) -->
<property name="hibernate.cache.provider_class">org.hibernate.cache.HashtableCacheProvider</property>
<!-- 開啟查詢緩存 -->
<property name="hibernate.cache.use_query_cache">true</property>
<!-- c. 指定哪一些類,需要加入二級緩存 -->
<class-cache usage="read-write" class="com.bie.lesson11.Dept"/>
<class-cache usage="read-only" class="com.bie.lesson11.Employee"/>
<!-- 集合緩存[集合緩存的元素對象,也加加入二級緩存] -->
<collection-cache usage="read-write" collection="com.bie.lesson11.Dept.emps"/>
        

   3.4:緩存策略:

<class-cache usage="read-only"/>     放入二級緩存的對象,只讀; 
<class-cache usage="nonstrict-read-write"/>  非嚴格的讀寫
<class-cache usage="read-write"/>    讀寫; 放入二級緩存的對象可以讀、寫;
<class-cache usage="transactional"/>   (基於事務的策略)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM