java中hibernate二級緩存詳解
Hibernate的二級緩存
一、緩存概述
緩存(Cache): 計算機領域非常通用的概念。它介于應用程序和永久性數(shù)據(jù)存儲源(如硬盤上的文件或者數(shù)據(jù)庫)之間,其作用是降低應用程序直接讀寫永久性數(shù)據(jù)存儲源的頻率,從而提高應用的運行性能。緩存中的數(shù)據(jù)是數(shù)據(jù)存儲源中數(shù)據(jù)的拷貝。緩存的物理介質(zhì)通常是內(nèi)存
hibernate中提供了兩個級別的緩存
第一級別的緩存是 Session 級別的緩存,它是屬于事務范圍的緩存。這一級別的緩存由 hibernate 管理的,一般情況下無需進行干預
第二級別的緩存是 SessionFactory 級別的緩存,它是屬于進程范圍的緩存
Hibernate 的緩存可以分為兩類:
內(nèi)置緩存: Hibernate 自帶的, 不可卸載. 通常在 Hibernate 的初始化階段, Hibernate 會把映射元數(shù)據(jù)和預定義的 SQL 語句放到 SessionFactory 的緩存中, 映射元數(shù)據(jù)是映射文件中數(shù)據(jù)的復制, 而預定義 SQL 語句時 Hibernate 根據(jù)映射元數(shù)據(jù)推到出來的. 該內(nèi)置緩存是只讀的.
外置緩存(二級緩存): 一個可配置的緩存插件. 在默認情況下, SessionFactory 不會啟用這個緩存插件. 外置緩存中的數(shù)據(jù)是數(shù)據(jù)庫數(shù)據(jù)的復制, 外置緩存的物理介質(zhì)可以是內(nèi)存或硬盤

二、理解二級緩存的并發(fā)訪問策略

三、配置進程范圍內(nèi)的二級緩存(配置ehcache緩存)
1 拷貝ehcache-1.5.0.jar到當前工程的lib目錄下
依賴 backport-util-concurrent 和 commons-logging
2 開啟二級緩存
<property name="hibernate.cache.use_second_level_cache">true</property>
3 要指定緩存的供應商
<property name="hibernate.cache.provider_class">
org.hibernate.cache.EhCacheProvider</property>
4 指定使用二級緩存的類
方法一 在使用類的*.hbm.xml配置
選擇需要使用二級緩存的持久化類, 設置它的二級緩存的并發(fā)訪問策略, <class> 元素的 cache 子元素表明 Hibernate 會緩存對象的簡單屬性, 但不會緩存集合屬性, 若希望緩存集合屬性中的元素, 必須在 <set> 元素中加入 <cache> 子元素
方法二 在hibernate.cfg.xml文件中配置(建議)
<!-- 指定使用二級緩存的類 放在maping下面 -->
<!-- 配置類級別的二級緩存 -->
<class-cache class="com.sihai.c3p0.Customer" usage="read-write"/>
<class-cache class="com.sihai.c3p0.Order" usage="read-write"/>
<!-- 配置集合級別的二級緩存 -->
<collection-cache collection="com.sihai.c3p0.Customer.orders"
usage="read-write"/>
5 配置ehcache默認的配置文件ehcache.xml(名字固定)(放在類路徑下)
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd"> <diskStore path="c:/ehcache"/> <defaultCache maxElementsInMemory="5" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true" maxElementsOnDisk="10000000" diskPersistent="false" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU" /> </ehcache>
四、 測試
package com.sihai.hibernate3.test;
import java.util.Iterator;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import com.sihai.hibernate3.demo1.Customer;
import com.sihai.hibernate3.demo1.Order;
import com.sihai.utils.HibernateUtils;
public class HibernateTest6 {
@Test
// 查詢緩存的測試
public void demo9(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
Query query = session.createQuery("select c.cname from Customer c");
// 使用查詢緩存:
query.setCacheable(true);
query.list();
tx.commit();
session = HibernateUtils.getCurrentSession();
tx = session.beginTransaction();
query = session.createQuery("select c.cname from Customer c");
query.setCacheable(true);
query.list();
tx.commit();
}
@SuppressWarnings("unused")
@Test
// 更新時間戳
public void demo8(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
Customer customer = (Customer) session.get(Customer.class, 2);
session.createQuery("update Customer set cname = '奶茶' where cid = 2").executeUpdate();
tx.commit();
session = HibernateUtils.getCurrentSession();
tx = session.beginTransaction();
Customer customer2 = (Customer) session.get(Customer.class, 2);
tx.commit();
}
@SuppressWarnings("all")
@Test
// 將內(nèi)存中的數(shù)據(jù)寫到硬盤
public void demo7(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
List<Order> list = session.createQuery("from Order").list();
tx.commit();
}
@Test
// 一級緩存的更新會同步到二級緩存:
public void demo6(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
Customer customer = (Customer) session.get(Customer.class, 1);
customer.setCname("芙蓉");
tx.commit();
session = HibernateUtils.getCurrentSession();
tx = session.beginTransaction();
Customer customer2 = (Customer) session.get(Customer.class, 1);
tx.commit();
}
@SuppressWarnings("unchecked")
@Test
// iterate()方法可以查詢所有信息.
// iterate方法會發(fā)送N+1條SQL查詢.但是會使用二級緩存的數(shù)據(jù)
public void demo5(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
// N+1條SQL去查詢.
Iterator<Customer> iterator = session.createQuery("from Customer").iterate();
while(iterator.hasNext()){
Customer customer = iterator.next();
System.out.println(customer);
}
tx.commit();
session = HibernateUtils.getCurrentSession();
tx = session.beginTransaction();
iterator = session.createQuery("from Customer").iterate();
while(iterator.hasNext()){
Customer customer = iterator.next();
System.out.println(customer);
}
tx.commit();
}
@SuppressWarnings("unchecked")
@Test
// 查詢所有.Query接口的list()方法.
// list()方法會向二級緩存中放數(shù)據(jù),但是不會使用二級緩存中的數(shù)據(jù).
public void demo4(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
// 查詢所有客戶:
// list方法會向二級緩存中放入數(shù)據(jù)的.
List<Customer> list = session.createQuery("from Customer").list();
for (Customer customer : list) {
System.out.println(customer.getCname());
}
tx.commit();
session = HibernateUtils.getCurrentSession();
tx = session.beginTransaction();
// Customer customer = (Customer) session.get(Customer.class, 1);// 沒有發(fā)生SQL ,從二級緩存獲取的數(shù)據(jù).
// list()方法沒有使用二級緩存的數(shù)據(jù).
list = session.createQuery("from Customer").list();
for (Customer customer : list) {
System.out.println(customer.getCname());
}
tx.commit();
}
@Test
// 二級緩存的集合緩沖區(qū)特點:
public void demo3(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
Customer customer = (Customer) session.get(Customer.class, 1);
// 查詢客戶的訂單.
System.out.println("訂單的數(shù)量:"+customer.getOrders().size());
tx.commit();
session = HibernateUtils.getCurrentSession();
tx = session.beginTransaction();
Customer customer2 = (Customer) session.get(Customer.class, 1);
// 查詢客戶的訂單.
System.out.println("訂單的數(shù)量:"+customer2.getOrders().size());
tx.commit();
}
@SuppressWarnings("unused")
@Test
// 配置二級緩存的情況
public void demo2(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
Customer customer1 = (Customer) session.get(Customer.class, 1);// 發(fā)送SQL.
Customer customer2 = (Customer) session.get(Customer.class, 1);// 不發(fā)送SQL.
System.out.println(customer1 == customer2);
tx.commit();
session = HibernateUtils.getCurrentSession();
tx = session.beginTransaction();
Customer customer3 = (Customer) session.get(Customer.class, 1);// 不發(fā)送SQL.
Customer customer4 = (Customer) session.get(Customer.class, 1);// 不發(fā)送SQL.
System.out.println(customer3 == customer4);
tx.commit();
}
@SuppressWarnings("unused")
@Test
// 沒有配置二級緩存的情況
public void demo1(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
Customer customer1 = (Customer) session.get(Customer.class, 1);// 發(fā)送SQL.
Customer customer2 = (Customer) session.get(Customer.class, 1);// 不發(fā)送SQL.
tx.commit();
session = HibernateUtils.getCurrentSession();
tx = session.beginTransaction();
Customer customer3 = (Customer) session.get(Customer.class, 1);// 發(fā)送SQL.
tx.commit();
}
}
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
SSh結(jié)合Easyui實現(xiàn)Datagrid的分頁顯示
這篇文章主要為大家詳細介紹了SSh結(jié)合Easyui實現(xiàn)Datagrid的分頁顯示的相關資料,感興趣的小伙伴們可以參考一下2016-06-06
Spring Boot項目添加外部Jar包以及配置多數(shù)據(jù)源的完整步驟
這篇文章主要給大家介紹了關于Spring Boot項目添加外部Jar包以及配置多數(shù)據(jù)源的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧2020-06-06
SpringBoot整合Minio的過程(支持公有及私有bucket)
Bucket 是存儲Object的邏輯空間,每個Bucket之間的數(shù)據(jù)是相互隔離的,對用戶而言,相當于存放文件的頂層文件夾,這篇文章主要介紹了SpringBoot整合Minio的過程(支持公有及私有bucket),需要的朋友可以參考下2025-03-03
Spring Boot Admin 動態(tài)修改日志級別的方法步驟
這篇文章主要介紹了Spring Boot Admin 動態(tài)修改日志級別的方法步驟,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-08-08

