1. 程式人生 > >Hibernate總結--一級快取和二級快取

Hibernate總結--一級快取和二級快取

在Hibernate中存在一級快取和二級快取,一級快取時Session 級別的快取,它是屬於事務範圍的快取,這一級別的快取由 hibernate 管理的。一級快取Hibernate預設會實現,當使用get或者load等方式查詢時會將結果存在Session中,在下一次查詢時。若是同一個Session,則Hibernate會先去Session查詢,然後再去查詢資料庫

Hibernate二級別的快取時 SessionFactory 級別的快取,它是屬於程序範圍的快取,二級快取查詢的時候會把查詢結果快取到二級快取中,如果同一個sessionFactory建立的某個session執行了相同的操作,hibernate就會從二級快取中拿結果,而不會再去連線資料庫。二級快取通常是藉助第三方外掛實現,如EhCache、OSCache。接下來主要講述藉助EhCache的使用

二級快取的使用

1.需要的jar包

ehcache-core-2.4.3.jar,hibernate-ehcache-4.1.1.Final.jar,slf4j-api-1.6.1.jar

2.將ehcache.xml 到當前 WEB 應用的類路徑下

<ehcache>

    <!-- Sets the path to the directory where cache .data files are created.

         If the path is a Java System Property it is replaced by
         its value in the running VM.

         The following properties are translated:
         user.home - User's home directory
         user.dir - User's current working directory
         java.io.tmpdir - Default temp file path -->
    <!-- 
                           磁碟的儲存的路徑 
                               指定一個目錄,當EHCache 把資料寫到硬碟上時,並把資料寫到這個目錄下:
    -->
    <diskStore path="java.io.tmpdir"/>


    <!--Default Cache configuration. These will applied to caches programmatically created through
        the CacheManager.

        The following attributes are required for defaultCache:

        maxInMemory       - Sets the maximum number of objects that will be created in memory
        eternal           - Sets whether elements are eternal. If eternal,  timeouts are ignored and the element
                            is never expired.
        timeToIdleSeconds - Sets the time to idle for an element before it expires. Is only used
                            if the element is not eternal. Idle time is now - last accessed time
        timeToLiveSeconds - Sets the time to live for an element before it expires. Is only used
                            if the element is not eternal. TTL is now - creation time
        overflowToDisk    - Sets whether elements can overflow to disk when the in-memory cache
                            has reached the maxInMemory limit.

        -->
    <!-- 設定預設的資料過期策略 -->
    <defaultCache
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="120"
        timeToLiveSeconds="120"
        overflowToDisk="true"
        />
    
    <!-- 設定具體的命名的資料過期策略,每個命名快取一個快取區域 -->
    <cache name="sampleCache1"
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="300"
        timeToLiveSeconds="600"
        overflowToDisk="true"
        />

    <!-- Sample cache named sampleCache2
        This cache contains 1000 elements. Elements will always be held in memory.
        They are not expired. -->
    <cache name="sampleCache2"
        maxElementsInMemory="1000"
        eternal="true"
        timeToIdleSeconds="0"
        timeToLiveSeconds="0"
        overflowToDisk="false"
        /> -->

    <!-- Place configuration for your caches following -->

</ehcache>

注:

A:<diskStore>: 指定一個目錄:當 EHCache 把資料寫到硬碟上時, 將把資料寫到這個目錄下.
B:<defaultCache>: 設定快取的預設資料過期策略      

 C:<cache> 設定具體的命名快取的資料過期策略。每個命名快取代表一個快取區域     
 D:Hibernate在不同的快取區域儲存不同的類/集合
        a:對於類而言,區域的名稱是類名。如:com.atguigu.domain.Customer        
        b:對於集合而言,區域的名稱是類名加屬性名。如         com.atguigu.domain.Customer.order

 E:ache 元素的屬性
        a:name:設定快取的名字,它的取值為類的全限定名或類的集合的名字
        b:maxElementsInMemory:設定基於記憶體的快取中可存放的物件最大數目
        c:eternal:設定物件是否為永久的,true表示永不過期,此時將忽略timeToIdleSeconds 和 timeToLiveSeconds屬性; 預設值是false 
        d:timeToIdleSeconds:設定物件空閒最長時間,以秒為單位, 超過這個時間,物件過期。當物件過期時,EHCache會把它從快取中清除。如果此值為0,表示物件可以無限期地處於空閒狀態。         f:timeToLiveSeconds:設定物件生存最長時間,超過這個時間,物件過期。如果此值為0,表示物件可以無限期地存在於快取中. 該屬性值必須大於或等於 timeToIdleSeconds 屬性值
        g:overflowToDisk:設定基於記憶體的快取中的物件數目達到上限後,是否把溢位的物件寫到基於硬碟的快取中 

3.配置 hibernate.cfg.xml 
       a:.配置啟用 hibernate 的二級快取
         <property name="cache.use_second_level_cache">true</property>
       b:配置hibernate二級快取使用的產品(根據對應的EhCacheRegionFactory 所在的路徑)
         <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>      
       c: 配置對哪些類使用 hibernate 的二級快取
         <class-cache usage="read-write" class="com.atguigu.hibernate.entities.Employee"/>

注:

查詢快取: 預設情況下, 設定的快取對 HQL 及 QBC 查詢時無效的, 但可以通過以下方式使其是有效的

A:在 hibernate 配置檔案中宣告開啟查詢快取
       <property name="cache.use_query_cache">true</property>

 B: 呼叫 Query 或 Criteria 的 setCacheable(true) 方法
C:查詢快取依賴於二級快取

4.測試類

package com.zhuojing.hibernate.secondlevelcache;

import static org.junit.Assert.*;

import java.util.Iterator;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.zhuojing.hibernate.hql.holleworld.Department;
import com.zhuojing.hibernate.hql.holleworld.Employee;

public class Hinernamte {

	private SessionFactory sessionFactory;
	private Session session;
	private Transaction transaction;
	
	@Before
	public void init(){
		Configuration configuration = new Configuration().configure();
		ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();
		sessionFactory = configuration.buildSessionFactory(serviceRegistry);
		session = sessionFactory.openSession();
		transaction = session.beginTransaction();
		//transaction.commit();
	}
	
	 @After
		public void destroy(){
			transaction.commit();
			session.close();
			sessionFactory.close();
		}
	@Test
	public void testSecondLevlCache() {
		Employee employee = (Employee)session.get(Employee.class, 2);
		System.out.println(employee.getName());
		
		transaction.commit();
		session.close();
		
		session = sessionFactory.openSession();
		transaction = session.beginTransaction();
		
		Employee employee1 = (Employee)session.get(Employee.class, 2);
		System.out.println(employee1.getName());
	}
	/**
	 * 集合的二級快取
	 */
	@Test
	public void testCollectionSecondCache(){
		
		Department department = (Department)session.get(Department.class, 2);
		System.out.println(department.getName());
		System.out.println(department.getEmployees().size());
		
		transaction.commit();
		session.close();
		
		session = sessionFactory.openSession();
		transaction = session.beginTransaction();
		
		Department department1 = (Department)session.get(Department.class, 2);
		System.out.println(department1.getName());
		System.out.println(department1.getEmployees().size());
		
	}
	
	/**
	 * 查詢快取
	 */
	@Test
	public void testQueryCache(){
		String hql = "FROM Employee";
		Query query = session.createQuery(hql);
		query.setCacheable(true);
		List<Employee> employees = query.list();
		System.out.println(employees.size());
		
		employees = query.list();
		System.out.println(employees.size());
	}

	@Test
	public void testIterator(){
		Department department = (Department)session.get(Department.class, 4);
		System.out.println(department.getName());
		System.out.println(department.getEmployees().size());
		
		Query query = session.createQuery("FROM Employee e where e.department.id = 4");
		Iterator<Employee> iterator = query.iterate();
		while(iterator.hasNext()){
			System.out.println(iterator.next().getName());
		}
	}
}

測試類主要說明,在session關閉的情況下在查詢,會直接從二級快取中取,就比如testSecondLevlCache方法和testCollectionSecondCache方法,testQueryCache方法是HQL查詢使用二級快取,testIterator是查詢集合