天天看點

【Hibernate】Hibernate建構單例SessionFactory

Hibernate常用的核心接口包括:

Configuration、SessionFactory、Session、Transaction、Query、Criteria。

在完成session擷取的過程中,主要涉及Configuration、SessionFactory、Session接口。

Configuration接口:負責配置并啟動Hibernate,建立SessionFactory對象。在Hibernate的啟動過程中,Configuration類的執行個體首先定位映射文檔位置,讀取配置,然後建立SessionFactory對象。

SessionFactory接口:負責初始化Hibernate,并負責建立Session對象。這裡用到了工廠模式,但是SessionFactory并不是輕量級的,因為在一般情況下,一個項目通常隻需要一個SessionFactory就足夠了,當需要操作多個資料庫時,可以定義多個SessionFactory。

Session接口:負責執行被持久化對象的CRUD操作,但是Session對象是非線程安全的。

ThreadLocal類用于在并發環境下避免競争,簡化程式設計的機制,它在并發環境下提供了一個邏輯上全局的通路點,來通路線程本地變量。ThreadLocal的功能非常簡單,就是為每一個使用該變量的線程都提供一個變量值的副本,是每一個線程都可以獨立的改變自己的副本,而不會和其他線程的副本沖突。從線程的角度來看,就好像每一個線程完全擁有該變量。

public class ThreadLocal {
	//HashMap存儲ThreadLocal變量,并實作了線程安全
	private Map values = Collections.synchronizedMap(new HashMap());
	public Object get(){
		Thread curThread = Thread.currentThread();
		Object obj = values.get(curThread);
		if(obj==null&&!values.containsKey(curThread)){
			obj = initialValue();
			values.put(curThread, obj);
		}
		return obj;
	}
	
	public void set(Object newValue){
		values.put(Thread.currentThread(), newValue);
	}
	
	public Object initialValue(){
		return null;
	}
}
           

SessionFactory在Hibernate中起到了一個緩沖區的作用,它緩沖了Hibernate自動生成的SQL語句和其他的映射資料,還緩沖了一些将來可能要重複利用的資料。首先介紹下Hibernate的傳遞配置屬性的三種方式:

No.1 使用hibernate.cfg.xml:

Configuration cfg = new Configuration();
cfg.configure("hibernate.cfg.xml");
           

No.2 使用hibernate.properties:

Configuration cfg = new Configuration();
cfg.configure("/hibernate.properties");
cfg.addResource("com/demo/hibernate/beans/User.hbm.xml");
或
Configuration cfg = new Configuration();
cfg.configure("/hibernate.properties");
cfg.addClass(com.demo.hibernate.beans.User.class);
           

No.3 構造時寫死:

Configuration cfg = new Configuration()
	.addClass(com.demo.hibernate.beans.User.class)
	.setProperty("hibernate.dialect","org.hibernate.dialect.MySQLInnoDBDialect");
	.setProperty("hibernate.connection","java:com/env/jdbc.test");
	.setProperty("hibernate.order_updates","true");
           

我們知道Configuration執行個體是一個啟動期間(sartup-time)的對象,一旦SessionFactory建立完成她就被丢棄。對于SessionFactory來說,它采用了工廠模式,使用者程式從工廠類SessionFactory中取得Session的執行個體,它的設計者的意圖是讓她在整個應用中共享。典型地說,一個項目通常隻需要一個SessionFactory就足夠了。是以,我們可以這樣定義SessionFactory類:

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;


public class HibernateSessionFactory {
	private static final Configuration cfg = new Configuration();
	private static org.hibernate.SessionFactory  sessionFactory;
	private static final ThreadLocal threadLocal = new ThreadLocal();
	
	public static Session currentSession() throws HibernateException{
		Session session = (Session)threadLocal.get();
		if(session == null){
			if(sessionFactory == null){
				try{
					cfg.configure("hibernate.cfg.xml");
					sessionFactory = cfg.buildSessionFactory();
				}catch(HibernateException e){
					System.out.println("Error Creating SessionFacotry.");
					e.printStackTrace();
				}
			}
			session = sessionFactory.openSession();
			threadLocal.set(session);
		}
		return session;
	}
	
	public static void cloaseSession() throws HibernateException{
		Session session = (Session)threadLocal.get();
		threadLocal.set(null);
		if(session != null){
			session.close();
		}
	}
}
           

總之,ThreadLocal讓一次程式的運作來使用一個Session,而所有的Session都公用一個SessionFacotry,這樣做有3個好處:

讓所有使用者共用一個SessionFactory,避免了重複建立SessionFactory而造成的資源浪費;

為每一個使用者通路都建立一個Session,避免了不同使用者之間的Session沖突;

在每一次程式運作的周期内,共用一個Session,既可以避免資源浪費,有提供了資源的共享,讓一次運作的多個操作共用一個Session資源,為事務的操作也提供了基礎。

是以,HibernateSessionFactory建立的執行個體關系圖如下:

【Hibernate】Hibernate建構單例SessionFactory

整個系統隻有一個Configuration和SessionFactory對象,而不同的使用者通路有不同的SessionA和SessionB。每一個Session在生命期内,都可以進行多個操作,直到線程通路結束。

繼續閱讀