1. 程式人生 > >SSH系列:Hibernate中的一級快取和快照

SSH系列:Hibernate中的一級快取和快照

      一級快取session:執行緒級別。 二級快取:程序級別
      快照:
      1、快照是資料的副本 
      2、快照屬於一級快取 
      3、快照是在堆記憶體中的 
      4、快照的作用:保證資料一致性 
      5、快照的理解:當執行session.getTransaction().commit()時,
      Hibernate同時會清理session的一級快取(flush),
      也就是將堆記憶體中的資料與快照中的資料進行對比,如果不一致,則會執行同步(update)操作,
      若相同,則不執行update。
    

舉個栗子:
例1、如下程式碼的執行過程就是如圖所示的執行過程,呼叫session.get()方法獲取user物件是持久態,堆區存在一級快取和快照。

@Test
	public void testCache1() {
		Session session = hibernateUtils.getOpenSession();
		User u1 = (User) session.get(User.class,1);  //持久態:有快取,且有快照
		//u1.setUsername("");
		session.update(u1);
		session.beginTransaction().commit();
		session.close();
	}

 例2、如下程式碼的執行過程就是如圖所示的執行過程,用new User()方法獲取user物件是瞬時態,當執行session.update()時,物件轉成持久態,堆區只存在一級快取。


	@Test
	public void testCache2() {
		Session session = hibernateUtils.getOpenSession();
		User u1 = new User(); //瞬時態
		u1.setUsername("張三");
		session.update(u1);  //有快取,但沒有快照
		session.beginTransaction().commit();
		session.close();
	}
	

 

 3、如下案例根據sql語句的列印次數,判斷存不存在一級快取。

package hibernate;

import static org.junit.Assert.*;

import java.util.List;

import hibernateUtils.hibernateUtils;

import org.hibernate.Session;
import org.junit.Before;
import org.junit.Test;

public class TestCache {
	
	@Test
	/*三條查同一個id的語句,只會查詢一次資料庫,然後放進一級快取session中,
	    第二第三次呼叫get方法就不會再查資料庫,直接從一級快取中取出
	 */
	public void testCache() {
		Session session = hibernateUtils.getOpenSession();
		User u1 = (User) session.get(User.class,1);
		User u2 = (User) session.get(User.class,1);
		User u3 = (User) session.get(User.class,1);
		System.out.println(u1);
		session.close();
	}
	
	@Test
	//hql:查詢語句一共輸出三次,所以hql沒有快取,更沒有快照
	public void testCache3() {
		Session session = hibernateUtils.getOpenSession();
		List<User> list = session.createQuery("from User").list();
		List<User> list1 = session.createQuery("from User").list();
		List<User> list2 = session.createQuery("from User").list();
		session.close();
	}
	
	@Test
	//hql:createQuery 下面再呼叫Get方法就存在快取了
	public void testCache4() {
		Session session = hibernateUtils.getOpenSession();
		List<User> list = session.createQuery("from User").list();  //列印select資料庫的語句
		User u1 = (User) session.get(User.class,1);  //不列印sql語句,也就是沒有查詢資料庫,說明有快取
		session.close();
	}
	
	@Test
	//查詢語句一共輸出三次,所以createCriteria沒有快取
	public void testCache5() {
		Session session = hibernateUtils.getOpenSession();
		List<User> list = session.createCriteria(User.class).list();  
		List<User> list1 = session.createCriteria(User.class).list();  
		List<User> list2 = session.createCriteria(User.class).list();  
		session.close();
	}
	@Test
	//查詢語句一共輸出三次,所以createSQLQuery沒有快取
	public void testCache6() {
		Session session = hibernateUtils.getOpenSession();
		List list = session.createSQLQuery("select * from t_user").list();  
		List list1 = session.createSQLQuery("select * from t_user").list();
		List list2 = session.createSQLQuery("select * from t_user").list();
		session.close();
	}

	@Test
	//查詢語句一共輸出三次,所以createCriteria沒有快取
	public void testCache7() {
		Session session = hibernateUtils.getOpenSession();
		List<User> list = session.createSQLQuery("select * from t_user").addEntity(User.class).list();  
		List<User> list1 = session.createSQLQuery("select * from t_user").addEntity(User.class).list();  
		List<User> list2 = session.createSQLQuery("select * from t_user").addEntity(User.class).list();  
		session.close();
	}
}