hibernate緩存

20.session的一級緩存

1.什麼是緩存?

緩存是介於物理數據源與應用程序之間,是對數據庫中的數據複製一份臨時放在內存中的容器,其作用是爲了減少應用程序對物理數據源訪問的次數,從而提高了應用程序的運行性能。Hibernate在進行讀取數據的時候,根據緩存機制在相應的緩存中查詢,如果在緩存中找到了需要的數據(我們把這稱做緩存命 中"),則就直接把命中的數據作爲結果加以利用,避免了大量發送SQL語句到數據庫查詢的性能損耗。

 

2.Hibernate緩存分類:

一、Session緩存(又稱作事務緩存):Hibernate內置的,不能卸除。

緩存範圍:緩存只能被當前Session對象訪問。緩存的生命週期依賴於Session的生命週期,當Session被關閉後,緩存也就結束生命週期。

 

二、SessionFactory緩存(又稱作應用緩存):使用第三方插件,可插拔。

緩存範圍:緩存被應用範圍內的所有session共享,不同的Session可以共享。這些session有可能是併發訪問緩存,因此必須對緩存進行更新。緩存的生命週期依賴於應用的生命週期,應用結束時,緩存也就結束了生命週期,二級緩存存在於應用程序範圍。

緩存策略提供商:

提供了HashTable緩存,EHCacheOSCacheSwarmCachejBoss Cathe2,這些緩存機制,其中EHCacheOSCache是不能用於集羣環境(Cluster Safe)的,而SwarmCachejBoss Cathe2是可以的。HashTable緩存主要是用來測試的,只能把對象放在內存中,EHCacheOSCache可以把對象放在內存(memory)中,也可以把對象放在硬盤(disk)上(爲什麼放到硬盤上?上面解釋了)。

 

 

session緩存:

   1、生命週期就是session的生命週期

   2session一級緩存存放的數據都是私有數據

        把session存放在threadlocal中,不同的線程是不能訪問的,所以保證了數據的安全性

   3、怎麼樣把數據存放到一級緩存中

        利用session.save/update/load/get方法都可以存放在一級緩存中

   4、利用session.get/load方法可以把數據從一級緩存中取出

   5session.evict方法可以把一個對象從一級緩存中清空

   6、利用session.clear方法可以把session中的所有的數據清空

   7、利用session.Refresh方法把數據庫中的數據同步到緩存中

   8session.flush

        在session的緩存內部,會去檢查所有的持久化對象

           1、如果一個持久化對象沒有ID值,則會發出insert語句

           2、如果一個持久化對象有ID值,則會去檢查快照進行對比,如果一樣,則什麼都不做,如果不一樣,則發出update語句

           3、檢查所有的持久化對象是否有關聯對象

                檢查關聯對象的級聯操作

                檢查關聯對象的關係操作

   9、批量操作


測試

public class SessionCacheTest extends HibernateUtils{
@Test
public void testGet(){
    Session session = sessionFactory.getCurrentSession();
    Transaction transaction = session.beginTransaction();
    Classess Classess = (Classess)session.get(Classess.class, 1L);
    Classess = (Classess)session.get(Classess.class,1L);
    transaction.commit();
}
/**
 * session.load方法把數據存放在一級緩存中
 */
@Test
public void testLoad(){
    Session session = sessionFactory.getCurrentSession();
    Transaction transaction = session.beginTransaction();
    Classess Classess = (Classess)session.load(Classess.class, 1L);
    Classess.getCname();
    Classess = (Classess)session.load(Classess.class,1L);
    Classess.getCname();
    transaction.commit();
}
/**
 * session.save方法把數據保存在一級緩存中
 */
@Test
public void testSave(){
    Session session = sessionFactory.getCurrentSession();
    Transaction transaction = session.beginTransaction();
    Classess Classess = new Classess();
    Classess.setCname("aaa");
    Classess.setDescription("asfd");
    session.save(Classess);
    Classess = (Classess)session.get(Classess.class, Classess.getCid());
    transaction.commit();
}
/**
 * session.update
 */
@Test
public void testUpdate(){
    Session session = sessionFactory.getCurrentSession();
    Transaction transaction = session.beginTransaction();
    Classess Classess = (Classess)session.get(Classess.class, 1L);
    session.evict(Classess);//Classess對象從session中清空了
    session.update(Classess);//把Classess對象放入到了session緩存中
    Classess = (Classess)session.get(Classess.class, 1L);
    transaction.commit();
}
/**
 * session.clear
 */
@Test
public void testClear(){
    Session session = sessionFactory.getCurrentSession();
    Transaction transaction = session.beginTransaction();
    Classess Classess = (Classess)session.get(Classess.class, 1L);
    session.clear();//Classess對象從session中清空了
    Classess = (Classess)session.get(Classess.class, 1L);
    transaction.commit();
}
@Test
public void testClearTest(){
    Session session = sessionFactory.getCurrentSession();
    Transaction transaction = session.beginTransaction();
    Classess Classess  = (Classess)session.get(Classess.class, 1L);
    session.clear();//如果不加這句話,兩個不同的對象,相同的ID值,所以得把其中的一個清空
    Classess Classess2 = new Classess();
    Classess2.setCid(1L);
    Classess2.setCname("asfd");
    session.update(Classess2);
    transaction.commit();
}
/**
 * 把數據庫中的數據刷新到緩存中
 */
@Test
public void testRefresh(){
    Session session = sessionFactory.getCurrentSession();
    Transaction transaction = session.beginTransaction();
    Classess Classess = (Classess)session.get(Classess.class, 1L);
    Classess.setCname("66");
    session.refresh(Classess);//把cid爲1的值從數據庫刷到了緩存中
    System.out.println(Classess.getCname());
    transaction.commit();
}
/**
 * session.flush
 */
@Test
public void testFlush(){
    Session session = sessionFactory.getCurrentSession();
    Transaction transaction = session.beginTransaction();
    Classess Classess  =(Classess)session.get(Classess.class, 1L);
    Classess.setCname("afdsasdf");
    Set<Student> students = Classess.getStudents();
    for(Student student:students){
        student.setDescription("asdf");
    }
    session.flush();
    transaction.commit();
}
 
/**
 * 批量操作
 */
@Test
public void testSaveBatch(){
    Session session = sessionFactory.getCurrentSession();
    Transaction transaction = session.beginTransaction();
    for(int i=6;i<1000000;i++){
        Classess Classess = new Classess();
        Classess.setCname("aaa");
        Classess.setDescription("afds");
        session.save(Classess);
        if(i%50==0){
            session.flush();
            session.clear();
        }
    }
    transaction.commit();
}
/**
 * session.flush只是發出SQL語句了,並沒有清空session緩存
 */
@Test
public void testFlush2(){
    Session session = sessionFactory.getCurrentSession();
    Transaction transaction = session.beginTransaction();
    Classess Classess = (Classess)session.get(Classess.class, 1L);
    session.flush();
    Classess = (Classess)session.get(Classess.class, 1L);
    transaction.commit();
    }
}

21.二級緩存

二級緩存:存放公有數據

   1、適用場合:

        1、數據不能頻繁更新

        2、數據能公開,私密性不是很強

   2hibernate本身並沒有提供二級緩存的解決方案

(1.hibernate中二級緩存用的不多,如果數據跟新頻繁,是不會放入二級緩存之中不會提高效率,2.如果不用跟新,直接和數據庫交互3.因爲是公有數據,每個線程訪問還有加密?不懂  )

   3、二級緩存的實現是依賴於第三方供應商完成的

         ehcache

         oscache

         jbosscache

         swamchache

   4、二級緩存的操作

         1、二級緩存存在sessionFactory

         2、生命週期:與sessionFactory保持一致(容器啓動sessionFactory產生,容器關閉sessionFactory關閉)

         3、使用二級緩存的步驟

             1、在hibernate.cfg.xml

                  <property name="cache.use_second_level_cache">true</property>

                  <property name="cache.provider_class">

                        org.hibernate.cache.EhCacheProvider

                  </property>

             2、讓某一個對象進入到二級緩存中

                 * 在配置文件中

                   <class-cache usage="read-only" class="cn.itcast.hiberate.sh.domain.Classes"/>

                 *  在映射文件中

                    <cache usage="read-only"/>

             3、使用

                  session.get/session.load

/**
 * session.get
 *    把數據存在一級緩存和二級緩存
 */
@Test
public void testGet11(){
    Session session = sessionFactory.openSession();
    Classess Classess = (Classess)session.get(Classess.class, 1L);
    session.close();
    session = sessionFactory.openSession();
    Classess = (Classess)session.get(Classess.class, 1L);
    session.close();
}
/**
 * session.load
 *   同上
 */
@Test
public void testLoad22(){
    Session session = sessionFactory.openSession();
    Classess Classess = (Classess)session.load(Classess.class, 1L);
    Classess.getCname();
    session.close();
    session = sessionFactory.openSession();
    Classess = (Classess)session.load(Classess.class, 1L);
    Classess.getCname();
    session.close();
}
/**
 * session.update
 */
@Test
public void testUpdate11(){
    Session session = sessionFactory.openSession();
    //session.beginTransaction();
    Classess Classess = new Classess();
    Classess.setCid(1L);
    Classess.setCname("aaa");
    session.update(Classess);
    session.close();
    session = sessionFactory.openSession();
    Classess = (Classess)session.get(Classess.class, 1L);
    session.close();
}


   5、查詢緩存

    在hibernate配置文件添加<property name="cache.use_query_cache">true</property>

  @Test
public void testQuery(){
    Session session = sessionFactory.openSession();
    Query query = session.createQuery("from Classess");
    query.setCacheable(true);//Classess裏的所有的數據要往查詢緩存中存放了
    List<Classess> ClassessList = query.list();
    query = session.createQuery("from Classess");//查詢緩存中的數據,sql語句必須和緩存的數據一致,才能利用查詢緩存
    query.setCacheable(true);//取出緩存數據
    ClassessList = query.list();
    session.close();
}

  


 6.大量數據緩存

    在src下添加一個配置文件ehcache.xml

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
         
    <diskStore path="D:\\TEMP1"/>
    <defaultCache
            maxElementsInMemory="12"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            overflowToDisk="false"
            maxElementsOnDisk="10000000"
            diskPersistent="false"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU"
            />
            
   <Cache
            name="cn.itcast.domain.Classes"
            maxElementsInMemory="5" 
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            overflowToDisk="true"
            maxElementsOnDisk="10000000"
            diskPersistent="false"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU"
            />
</ehcache>
@Test
public void testAllClassess(){
    Session session = sessionFactory.openSession();
    List<Classess> ClassessList = session.createQuery("from Classess").list();
    session.close();
    try {
    Thread.sleep(1000);
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章