国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Java > 正文

Hibernate緩存詳解

2019-11-26 13:09:14
字體:
來源:轉載
供稿:網友

1. 什么是緩存?

數據庫的緩存指的是應用程序和物理數據源之間的數據。即把物理數據源的數據復制到緩存。有了緩存,可以降低應用程序對物理數據源的訪問頻率,從而提高效率。緩存的介質一般是內存,也可以是硬盤。

Hibernate的緩存有三種類型:一級緩存、二級緩存和查詢緩存。

2. 一級緩存

一級緩存即Session緩存,由Session自動進行管理,不需要程序進行干預。一級緩存根據對象的ID進行加載和緩存。如下面的代碼:

@Override  public void testCache() {    // TODO Auto-generated method stub    Session session = sessionFactory.openSession();    Transaction tx = session.beginTransaction();     Course c = (Course) session.get(Course.class, 1);    System.out.println("Name:" + c.getName());    c = (Course) session.get(Course.class, 1);    System.out.println("Name:" + c.getName());    tx.commit();    session.close();  }

運行結果:

Hibernate:   select    course0_.ID as ID0_0_,    course0_.NAME as NAME0_0_,    course0_.COMMENT as COMMENT0_0_   from    clas course0_   where    course0_.ID=?Name:計算機原理Name:計算機原理

第1次查詢時生成了SQL語句,并將查詢出來的對象放在一級緩存里面,第2次查詢時,在一級緩存里面直接找到了這個對象,就不需要再次生成SQL語句了。

再看一個例子:

@Override  public void testCache() {    // TODO Auto-generated method stub    Session session = sessionFactory.openSession();    Transaction tx = session.beginTransaction();     Course c = (Course) session.get(Course.class, 1);    System.out.println("Name:" + c.getName());    tx.commit();    session.close();    session = sessionFactory.openSession();    tx = session.beginTransaction();     c = (Course) session.get(Course.class, 1);    System.out.println("Name:" + c.getName());    tx.commit();    session.close();  }

由于一級緩存是Session級別的緩存,所以Session關閉以后,一級緩存也就不存在了,第2次查詢也要生成SQL語句:

Hibernate:   select    course0_.ID as ID0_0_,    course0_.NAME as NAME0_0_,    course0_.COMMENT as COMMENT0_0_   from    clas course0_   where    course0_.ID=?Name:計算機原理Hibernate:   select    course0_.ID as ID0_0_,    course0_.NAME as NAME0_0_,    course0_.COMMENT as COMMENT0_0_   from    clas course0_   where    course0_.ID=?Name:計算機原理

 3. 二級緩存

二級緩存即SessionFactory緩存,和一級緩存類似,也是根據對象的ID進行加載和緩存,區別就在于一級緩存只在Session內有效,而二級緩存在SessionFactory內有效。在訪問某個ID的對象時,先到一級緩存里面去找,如果沒有找到就到二級緩存里面去找。二級緩存包括EHCache,OSCache,SwarmCache和JBossCache等。這里以EHCache作為例子。

二級緩存需要程序進行管理。首先,配置Maven下載相關的Jar,在pom文件里面添加:

<dependency>       <groupId>org.hibernate</groupId>       <artifactId>hibernate-ehcache</artifactId>       <version>4.1.0.Final</version>     </dependency>    <dependency>       <groupId>net.sf.ehcache</groupId>       <artifactId>ehcache</artifactId>       <version>2.8.3</version>     </dependency>

創建EHCache配置文件ehcache.xml:

<ehcache>  <diskStore path="E:/Eclipse/MyWorkspace/Cache"/>  <defaultCache    maxElementsInMemory="10000"    eternal="true"    timeToIdleSeconds="120"    timeToLiveSeconds="120"    overflowToDisk="true"  />  <cache name="com.hzhi.course.entity.Course"    maxElementsInMemory="10000"    eternal="true"    timeToIdleSeconds="300"    timeToLiveSeconds="600"    overflowToDisk="true"  /></ehcache>

defaultCache是默認的設置,下面一個cache指明了對哪一個類進行二級緩存。里面設置了最大緩存的對象數量,是否永久有效、最大空閑秒數、最大生存秒數、內存滿時是否寫到硬盤,寫到硬盤的路徑等等。

修改需要緩存的類的hbm文件:

 <class name="com.hzhi.course.entity.Course" table="clas">    <cache usage="read-only"/>        ......  </class>

usage設置了并發訪問策略,一般設置成read-only。

修改applicationContext.xml中的SessionFactory的配置,增加二級緩存的一些屬性:

<!-- SessionFactory -->   <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">    <property name="dataSource" >      <ref local="dataSource"/>    </property>    <!-- 配置Hibernate的屬性 -->    <property name="hibernateProperties">      <props>        <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>        <prop key="hibernate.show_sql">true</prop>        <prop key="hibernate.format_sql">true</prop>        <prop key="hibernate.connection.isolation">8</prop>        <!-- 二級緩存 -->        <prop key="hibernate.cache.use_second_level_cache">false</prop>        <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>                <prop key="hibernate.cache.provider_configuration_file_resource_path">WEB-INF/ehcache.xml</prop>              </props>    </property>     ......   </bean>

運行下面的例子:

@Override  public void testCache() {    // TODO Auto-generated method stub    Session session = sessionFactory.openSession();    Transaction tx = session.beginTransaction();     Course c = (Course) session.get(Course.class, 1);    System.out.println("Name:" + c.getName());    tx.commit();    session.close();    session = sessionFactory.openSession();    tx = session.beginTransaction();     c = (Course) session.get(Course.class, 1);    System.out.println("Name:" + c.getName());    tx.commit();    session.close();  }

結果:

Hibernate:   select    course0_.ID as ID0_0_,    course0_.NAME as NAME0_0_,    course0_.COMMENT as COMMENT0_0_   from    clas course0_   where    course0_.ID=?Name:計算機原理Name:計算機原理

雖然關閉了Session,但是二級緩存仍然存在,所以只生成了一次SQL語句。

下面的例子:

@Override  public void testCache() {    // TODO Auto-generated method stub    Session session = sessionFactory.openSession();    Transaction tx = session.beginTransaction();     Query query = session.createQuery("from Course");     Iterator iter = query.iterate();     while(iter.hasNext()){         System.out.println(((Course)iter.next()).getName());     }    tx.commit();    session.close();        session = sessionFactory.openSession();    tx = session.beginTransaction();     query = session.createQuery("from Course");     iter = query.iterate();     while(iter.hasNext()){         System.out.println(((Course)iter.next()).getName());     }    tx.commit();    session.close();  }

結果:

Hibernate:   select    course0_.ID as col_0_0_   from    clas course0_Hibernate:   select    course0_.ID as ID0_0_,    course0_.NAME as NAME0_0_,    course0_.COMMENT as COMMENT0_0_   from    clas course0_   where    course0_.ID=?計算機原理Hibernate:   select    course0_.ID as ID0_0_,    course0_.NAME as NAME0_0_,    course0_.COMMENT as COMMENT0_0_   from    clas course0_   where    course0_.ID=?計算機網絡Hibernate:   select    course0_.ID as ID0_0_,    course0_.NAME as NAME0_0_,    course0_.COMMENT as COMMENT0_0_   from    clas course0_   where    course0_.ID=?數據庫原理Hibernate:   select    course0_.ID as ID0_0_,    course0_.NAME as NAME0_0_,    course0_.COMMENT as COMMENT0_0_   from    clas course0_   where    course0_.ID=?C語言Hibernate:   select    course0_.ID as ID0_0_,    course0_.NAME as NAME0_0_,    course0_.COMMENT as COMMENT0_0_   from    clas course0_   where    course0_.ID=?大學英語AHibernate:   select    course0_.ID as ID0_0_,    course0_.NAME as NAME0_0_,    course0_.COMMENT as COMMENT0_0_   from    clas course0_   where    course0_.ID=?JavaHibernate:   select    course0_.ID as ID0_0_,    course0_.NAME as NAME0_0_,    course0_.COMMENT as COMMENT0_0_   from    clas course0_   where    course0_.ID=?LinuxHibernate:   select    course0_.ID as ID0_0_,    course0_.NAME as NAME0_0_,    course0_.COMMENT as COMMENT0_0_   from    clas course0_   where    course0_.ID=?高等數學Hibernate:   select    course0_.ID as ID0_0_,    course0_.NAME as NAME0_0_,    course0_.COMMENT as COMMENT0_0_   from    clas course0_   where    course0_.ID=?語文Hibernate:   select    course0_.ID as ID0_0_,    course0_.NAME as NAME0_0_,    course0_.COMMENT as COMMENT0_0_   from    clas course0_   where    course0_.ID=?大學物理Hibernate:   select    course0_.ID as ID0_0_,    course0_.NAME as NAME0_0_,    course0_.COMMENT as COMMENT0_0_   from    clas course0_   where    course0_.ID=?軟件工程Hibernate:   select    course0_.ID as col_0_0_   from    clas course0_計算機原理計算機網絡數據庫原理C語言大學英語AJavaLinux高等數學語文大學物理軟件工程

當使用Query的list()方法時,只生成一次SQL語句查詢出所有的對象,使用iterate()方法時,會先得到所有對象的ID,然后根據每個ID生成一次SQL語句查詢。第二個Session里面使用的也是iterate()方法,首先生成一次SQL語句,得到ID,然后根據ID查找對象,由于開啟了二級緩存,在二級緩存里面找到了對象,所以就直接輸出了,并沒有再根據每個ID生成SQL語句。

不論是一級緩存還是二級緩存,都只能緩存對象,不能緩存屬性的值。下面的例子:

@Override  public void testCache() {    // TODO Auto-generated method stub    Session session = sessionFactory.openSession();    Transaction tx = session.beginTransaction();     Query query = session.createQuery("select c.name from Course c");      List<String> names = query.list();     for(Iterator iter = names.iterator(); iter.hasNext();){       String name = (String) iter.next();       System.out.println(name);     }     System.out.println("----------");     query = session.createQuery("select c.name from Course c");      names = query.list();     for(Iterator iter = names.iterator(); iter.hasNext();){       String name = (String) iter.next();       System.out.println(name);     }     System.out.println("----------");     tx.commit();    session.close();  }

運行結果:

Hibernate:   select    course0_.NAME as col_0_0_   from    clas course0_計算機原理計算機網絡數據庫原理C語言大學英語AJavaLinux高等數學語文大學物理軟件工程----------Hibernate:   select    course0_.NAME as col_0_0_   from    clas course0_計算機原理計算機網絡數據庫原理C語言大學英語AJavaLinux高等數學語文大學物理軟件工程----------

雖然開啟了二級緩存,但是查詢的結果不是對象,是屬性,所以并沒有緩存,第2次查詢仍然生成了查詢語句。要解決這個問題,就需要查詢緩存。

3. 查詢緩存

在配置了二級緩存的基礎上,可以設置查詢緩存,在SessionFactory的設置里面加上一行:

<prop key="hibernate.cache.use_query_cache">true</prop>

即打開了查詢緩存。查詢緩存也是SessionFactory級別的緩存,在整個SessionFactory里面都是有效的。

關閉二級緩存,運行下面的例子,在Query后面添加setCacheable(true)打開查詢緩存:

@Override  public void testCache() {    // TODO Auto-generated method stub    Session session = sessionFactory.openSession();    Transaction tx = session.beginTransaction();     Query query = session.createQuery("select c.name from Course c");     query.setCacheable(true);     List<String> names = query.list();     for(Iterator iter = names.iterator(); iter.hasNext();){       String name = (String) iter.next();       System.out.println(name);     }     System.out.println("----------");     query = session.createQuery("select c.name from Course c");     query.setCacheable(true);     names = query.list();     for(Iterator iter = names.iterator(); iter.hasNext();){       String name = (String) iter.next();       System.out.println(name);     }     System.out.println("----------");     tx.commit();    session.close();  }

結果:

Hibernate:   select    course0_.NAME as col_0_0_   from    clas course0_計算機原理計算機網絡數據庫原理C語言大學英語AJavaLinux高等數學語文大學物理軟件工程----------計算機原理計算機網絡數據庫原理C語言大學英語AJavaLinux高等數學語文大學物理軟件工程----------

由于兩次查詢的HQL語句是一致的,所以只生成一次SQL語句。但是如果把第二次查詢改一下:

System.out.println("----------");     query = session.createQuery("select c.name from Course c where c.id > 5");     query.setCacheable(true);     names = query.list();     for(Iterator iter = names.iterator(); iter.hasNext();){       String name = (String) iter.next();       System.out.println(name);     }     System.out.println("----------");

結果:

Hibernate:   select    course0_.NAME as col_0_0_   from    clas course0_計算機原理計算機網絡數據庫原理C語言大學英語AJavaLinux高等數學語文大學物理軟件工程----------Hibernate:   select    course0_.NAME as col_0_0_   from    clas course0_   where    course0_.ID>5大學英語AJavaLinux高等數學語文大學物理軟件工程----------

由于HQL語句變了,所以第二次也生成了SQL語句。

查詢緩存可以緩存屬性,也可以緩存對象,但是當緩存對象時,只緩存對象的ID,不會緩存整個對象。下面的例子:

@Override  public void testCache() {    // TODO Auto-generated method stub    Session session = sessionFactory.openSession();    Transaction tx = session.beginTransaction();     Query query = session.createQuery("from Course");    query.setCacheable(true);    List<Course> list = query.list();    for (int i=0; i<list.size(); i++){      System.out.println(list.get(i).getName());     }    System.out.println("----------");     tx.commit();    session.close();    session = sessionFactory.openSession();    tx = session.beginTransaction();        query = session.createQuery("from Course");     query.setCacheable(true);    list = query.list();    for (int i=0; i<list.size(); i++){      System.out.println(list.get(i).getName());     }    System.out.println("----------");    tx.commit();    session.close();  }

 結果:

 Hibernate:   select    course0_.ID as ID0_,    course0_.NAME as NAME0_,    course0_.COMMENT as COMMENT0_   from    clas course0_計算機原理計算機網絡數據庫原理C語言大學英語AJavaLinux高等數學語文大學物理軟件工程----------Hibernate:   select    course0_.ID as ID0_0_,    course0_.NAME as NAME0_0_,    course0_.COMMENT as COMMENT0_0_   from    clas course0_   where    course0_.ID=?Hibernate:   select    course0_.ID as ID0_0_,    course0_.NAME as NAME0_0_,    course0_.COMMENT as COMMENT0_0_   from    clas course0_   where    course0_.ID=?Hibernate:   select    course0_.ID as ID0_0_,    course0_.NAME as NAME0_0_,    course0_.COMMENT as COMMENT0_0_   from    clas course0_   where    course0_.ID=?Hibernate:   select    course0_.ID as ID0_0_,    course0_.NAME as NAME0_0_,    course0_.COMMENT as COMMENT0_0_   from    clas course0_   where    course0_.ID=?Hibernate:   select    course0_.ID as ID0_0_,    course0_.NAME as NAME0_0_,    course0_.COMMENT as COMMENT0_0_   from    clas course0_   where    course0_.ID=?Hibernate:   select    course0_.ID as ID0_0_,    course0_.NAME as NAME0_0_,    course0_.COMMENT as COMMENT0_0_   from    clas course0_   where    course0_.ID=?Hibernate:   select    course0_.ID as ID0_0_,    course0_.NAME as NAME0_0_,    course0_.COMMENT as COMMENT0_0_   from    clas course0_   where    course0_.ID=?Hibernate:   select    course0_.ID as ID0_0_,    course0_.NAME as NAME0_0_,    course0_.COMMENT as COMMENT0_0_   from    clas course0_   where    course0_.ID=?Hibernate:   select    course0_.ID as ID0_0_,    course0_.NAME as NAME0_0_,    course0_.COMMENT as COMMENT0_0_   from    clas course0_   where    course0_.ID=?Hibernate:   select    course0_.ID as ID0_0_,    course0_.NAME as NAME0_0_,    course0_.COMMENT as COMMENT0_0_   from    clas course0_   where    course0_.ID=?Hibernate:   select    course0_.ID as ID0_0_,    course0_.NAME as NAME0_0_,    course0_.COMMENT as COMMENT0_0_   from    clas course0_   where    course0_.ID=?計算機原理計算機網絡數據庫原理C語言大學英語AJavaLinux高等數學語文大學物理軟件工程----------

由于開了查詢緩存,沒有開二級緩存,雖然使用的是list()方法一次查詢出了所有的對象,但是查詢緩存只緩存了對象ID,沒有緩存整個對象。所以在第2個Session里面"from Course"這個HQL由于和前面的相同,并沒有生成SQL語句,但是由于沒有開二級緩存,沒有緩存整個對象,只能根據每個ID去生成一次SQL語句。雖然兩次用的都是list()方法,但是第一次是生成SQL語句去一次查詢出所有的對象,而第二次是根據查詢緩存里面的ID一個一個的生成SQL語句。

如果同時打開查詢緩存和二級緩存,第2個Session里面就不用再根據ID去生成SQL語句了:

Hibernate:   select    course0_.ID as ID0_,    course0_.NAME as NAME0_,    course0_.COMMENT as COMMENT0_   from    clas course0_計算機原理計算機網絡數據庫原理C語言大學英語AJavaLinux高等數學語文大學物理軟件工程----------計算機原理計算機網絡數據庫原理C語言大學英語AJavaLinux高等數學語文大學物理軟件工程----------

以上就是本文的全部內容,希望本文的內容對大家的學習或者工作能帶來一定的幫助,同時也希望多多支持武林網!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 乳山市| 会同县| 香格里拉县| 红原县| 上虞市| 霍邱县| 客服| 军事| 繁昌县| 专栏| 枣强县| 扶沟县| 扶风县| 阿克陶县| 襄樊市| 东丰县| 宁阳县| 乌拉特前旗| 论坛| 平乡县| 济阳县| 固安县| 揭西县| 克什克腾旗| 高唐县| 巧家县| 庆云县| 武夷山市| 汽车| 巴楚县| 临夏县| 宝丰县| 昌邑市| 松溪县| 兰坪| 文昌市| 彰化县| 罗源县| 合川市| 二连浩特市| 运城市|