【Hibernate筆記整理七】緩存機制與事務管理

版權聲明:本文爲 小異常 原創文章,非商用自由轉載-保持署名-註明出處,謝謝!
本文網址: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 層進行事務管理,就必須要保證連接對象是同一個。對於實現同一個連接對象有兩個辦法:

  1. 向下傳遞

    在外面獲得一個連接,直接傳入 Dao 層,在 Dao 層中直接使用外面傳來的這個連接對象就可以了,DBUtils 這個小工具就是採用了這個辦法。

  2. 使用 ThreadLocal 對象

    這個對象是綁定線程的對象,將連接對象綁定到當前線程中,然後在 Dao 層的方法中,直接通過當前線程來獲得這個連接對象即可。
     
    Hibernate 框架採用了第二個辦法,它的內部已經綁定好了 ThreadLocal 對象,在 SessionFactory 中提供了一個方法 getCurrentSession(),通過這個方法能獲得當前線程中的 Session,但是這個方法默認是不能使用的,需要通過配置才能開啓使用。

Hibernate 解決 Service 層事務管理的步驟如下:

1)配置 Session 管理方式

Hibernate 的配置文件中,我們可以使用 hibernate.current_session_context_class 屬性來設置 Session 管理方式,它的可選值有:

  • thread:Session 對象的生命週期與本地線程綁定;
  • jta:Session 對象的生命週期與 JTA 事務綁定;
  • managedHibernate 委託當前程序來管理 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();
	}
	
}


博客中若有不恰當的地方,請您一定要告訴我。前路崎嶇,望我們可以互相幫助,並肩前行!



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章