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是查詢集合