版權聲明:本文爲 小異常 原創文章,非商用自由轉載-保持署名-註明出處,謝謝!
本文網址:https://blog.csdn.net/sun8112133/article/details/106151531
文章目錄
一、緩存機制
1、緩存概述
緩存 是一種優化的方式,將數據存入到內存中,使用的時候會直接從這塊內存中獲取,不用通過存儲源,這塊內存我們把它稱之爲 緩存。
在 Hibernate 中提供了很多種優化手段,比如緩存機制、抓取策略等。他們的目的只有一個,就是儘可能的提高性能。本章主要講解 Hibernate 中的第一個優化手段 —— 緩存機制。
2、Hibernate 中的緩存(一級緩存)
在 Hibernate 中提供了兩種緩存機制:一級緩存 和 二級緩存。
一級緩存 是 Session 級別的緩存,它的生命週期與 Session 一致(一級緩存 是由 Session 中一系列的 Java 集合構成的)。它是 Hibernate 自帶的,不可以棄用。
而 Hibernate 的 二級緩存 是 SessionFactory 級別的緩存,它必須手動開啓才能使用,一般項目中很少使用,一般都用 Redis 來代替,大家瞭解一下有這麼個東西就可以了。
1)特點
當應用程序調用 Session 接口的
save()
、update()
、saveOrUpdate()
方法時,如果 Session 緩存(一級緩存)中沒有相應的對象,Hibernate 就會自動的把從數據庫中查詢到的對象信息加入到 一級緩存 中去。當調用 Session 接口的
load()
、get()
方法,以及 Query 接口中的list()
、iterator()
方法時,會判斷緩存中是否存在該對象,有則返回,不會查詢數據庫;如果緩存中沒有要查詢的對象,再去數據庫中查詢對應的對象,並添加到 一級緩存 中。當調用 Session 的
close()
方法時,Session 緩存(一級緩存)會被清空。
@Test
// 證明一級緩存的存在
public void demo3() {
Session session = HibernateUtils.openSession(); // HibernateUtils是自己封裝的工具類,從中獲取 Session 對象
Transaction tx = session.beginTransaction();
// Customer c = session.get(Customer.class, 1); // 第一次會從數據庫中取,會發送SQL語句
// System.out.println(c);
// Customer c2 = session.get(Customer.class, 1); // 緩存中存在,會直接從緩存中取,不會發送SQL語句
// System.out.println(c2);
Customer c = new Customer();
c.setCust_name("張三");
Serializable id = session.save(c); // 插入到數據庫中,並插入到緩存中
Customer c2 = session.get(Customer.class, id); // 會直接從緩存中取
System.out.println(c2);
tx.commit();
session.close();
}
2)清空
@Test
// 一級緩存的清空
public void demo4() {
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
Customer c1 = session.get(Customer.class, 1); // 發送SQL語句,將數據放到緩存中(持久化對象)
System.out.println(c1);
// 清空Session緩存中的數據
// session.clear(); // 清空全部數據
session.evict(c1); // 清空指定對象
Customer c2 = session.get(Customer.class, 1); // 發送SQL語句,將數據放到緩存中(持久化對象)
System.out.println(c2);
tx.commit();
session.close();
}
二、事務管理
關於 事務 這一塊,我之前寫過一篇關於 事務 的博客,自我感覺寫的還算通俗易懂,大家可以參考參考:事務博客
1、配置事務隔離級別
在
hibernate.cfg.xml
中進行 配置事務隔離級別,如下:
<!-- 設置事務隔離級別
1 -- Read uncommitted isolation(讀未提交)
2 -- Read committed isolation(讀已提交)
4 -- Repeatable read isolation(可重複讀)
8 -- Serializable isolation(序列化)
-->
<property name="hibernate.connection.isolation">4</property>
2、Service 層的事務
我們如果要在 Service 層進行事務管理,就必須要保證連接對象是同一個。對於實現同一個連接對象有兩個辦法:
向下傳遞
在外面獲得一個連接,直接傳入 Dao 層,在 Dao 層中直接使用外面傳來的這個連接對象就可以了,DBUtils 這個小工具就是採用了這個辦法。
使用 ThreadLocal 對象
這個對象是綁定線程的對象,將連接對象綁定到當前線程中,然後在 Dao 層的方法中,直接通過當前線程來獲得這個連接對象即可。
Hibernate 框架採用了第二個辦法,它的內部已經綁定好了 ThreadLocal 對象,在 SessionFactory 中提供了一個方法getCurrentSession()
,通過這個方法能獲得當前線程中的 Session,但是這個方法默認是不能使用的,需要通過配置才能開啓使用。Hibernate 解決 Service 層事務管理的步驟如下:
1)配置 Session 管理方式
在 Hibernate 的配置文件中,我們可以使用
hibernate.current_session_context_class
屬性來設置 Session 管理方式,它的可選值有:
thread
:Session 對象的生命週期與本地線程綁定;jta
:Session 對象的生命週期與 JTA 事務綁定;managed
:Hibernate 委託當前程序來管理 Session 對象的生命週期。
在
hibernate.cfg.xml
中進行如下配置:
<!-- 配置當前線程綁定的 Session -->
<property name="hibernate.current_session_context_class">thread</property>
2)測試
注意:在使用
getCurrentSession()
方法是不能關閉 Session 對象的,因爲在線程結束後會自動關閉 Session 對象,如果手動關閉就會報錯!
@Test
public void demo1() {
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
Customer c = session.get(Customer.class, 1);
System.out.println(c);
tx.commit();
}
3)封裝 HibernateUtils 工具類
/**
* Hibernate的工具類
* @author Administrator
*
*/
public class HibernateUtils {
private static Configuration cfg = null;
private static SessionFactory sf = null;
static {
cfg = new Configuration().configure();
sf = cfg.buildSessionFactory();
}
public static Session openSession() {
return sf.openSession();
}
public static Session getCurrentSession() {
return sf.getCurrentSession();
}
}