SessionFactory 執行緒安全,可共享。Session 非執行緒安全,包含資料庫連線、快取等狀態,多執行緒共用會導致資料錯亂。內部維護一個 Map,鍵為當前執行緒,值為該執行緒專屬的變數副本。get() 若無值則呼叫 initialValue() 初始化;set() 綁定新值。簡化版實作:
public class ThreadLocal {
private final Map values = Collections.synchronizedMap(new HashMap<>());
public T get() {
Thread t = Thread.currentThread();
T val = values.get(t);
if (val == null && !values.containsKey(t)) {
val = initialValue();
values.put(t, val);
}
return val;
}
public void set(T val) { values.put(Thread.currentThread(), val); }
protected T initialValue() { return null; }
}
public final class HibernateUtil {
private static final SessionFactory SESSION_FACTORY = buildSessionFactory();
private static final ThreadLocal TL_SESSION = new ThreadLocal<>();
private static SessionFactory buildSessionFactory() {
try { return new Configuration().configure().buildSessionFactory(); }
catch (Throwable ex) { throw new ExceptionInInitializerError(ex); }
}
public static Session currentSession() throws HibernateException {
Session s = TL_SESSION.get();
if (s == null) {
s = SESSION_FACTORY.openSession();
TL_SESSION.set(s);
}
return s;
}
public static void closeSession() throws HibernateException {
Session s = TL_SESSION.get();
if (s != null) { s.close(); }
TL_SESSION.set(null); // 移除引用,防記憶體洩漏
}
}
finally 區塊呼叫 closeSession(),釋放資料庫連線並清除 ThreadLocal 引用。