代碼詳解:
/**
* 框架工具代碼. 實(shí)現(xiàn)創(chuàng)建會(huì)話(huà)對(duì)象的功能.
* 代碼中封裝一個(gè)會(huì)話(huà)工廠對(duì)象. 提供一個(gè)靜態(tài)訪問(wèn)方法.獲取會(huì)話(huà) 對(duì)象.
*
* 分析:
* 會(huì)話(huà)工廠創(chuàng)建的個(gè)數(shù),次數(shù).
* 工廠創(chuàng)建一個(gè). 創(chuàng)建一次.
*
* java中,什么代碼可以保證,一次虛擬機(jī)生命周期,運(yùn)行唯一一次.
*
* @author Administrator
*
*/
public class MyBatisUtils{
private static SqlSessionFactory sqlSessionFactory;
private static Map<Thread, SqlSession> currentSessions = new HashMap<>();
/*
* 用戶(hù)維護(hù)線程資源的一個(gè)控制對(duì)象.
* 可以保證,相同的線程中,只有唯一的一個(gè)資源對(duì)象,與之對(duì)應(yīng).
* 功能類(lèi)似自定義的屬性currentSessions
* 結(jié)構(gòu)和currentSessions幾乎一樣.
* ThreadLocal中有屬性,Map集合類(lèi)型的屬性.
* 集合的key是當(dāng)前線程對(duì)象, 集合的value是要綁定的資源對(duì)象.
* 常用方法 :
* set(T t) -> map.put(Thread.currentThread(), t);
* get() -> map.get(Thread.currentThread());
* remove() -> map.remove(Thread.currentThread());
*/
private static ThreadLocal<SqlSession> localSessions = new ThreadLocal<>();
static{
// 創(chuàng)建會(huì)話(huà)工廠的代碼.
try{
sqlSessionFactory = new SqlSessionFactoryBuilder().build(
Resources.getResourceAsStream("mybatis.cfg.xml")
);
}catch(Exception e){
// 靜態(tài)代碼塊出現(xiàn)異常.中斷JVM
// 拋出一個(gè)初始化代碼異常錯(cuò)誤.
throw new ExceptionInInitializerError(e);
}
}
/*
* 會(huì)話(huà)對(duì)象創(chuàng)建方法
* 功能增強(qiáng). 一個(gè)線程,多次訪問(wèn)當(dāng)前方法,只創(chuàng)建唯一的一個(gè)會(huì)話(huà)對(duì)象.
* 線程有對(duì)象. Thread類(lèi)型的對(duì)象就是線程.
* 如何獲取當(dāng)前線程? Thread.currentThread();
* 使用當(dāng)前線程對(duì)象作為key,SqlSession對(duì)象作為value,創(chuàng)建一個(gè)Map集合.管理會(huì)話(huà)對(duì)象.
*/
public static SqlSession openSession(){
// 1. 獲取當(dāng)前線程中對(duì)應(yīng)的會(huì)話(huà)對(duì)象.
// SqlSession session = currentSessions.get(Thread.currentThread());
SqlSession session = localSessions.get();
// 2. 判斷獲取的會(huì)話(huà)對(duì)象是否為null
if(session == null){
// 當(dāng)前線程未創(chuàng)建過(guò)會(huì)話(huà)對(duì)象.
session = sqlSessionFactory.openSession();
// currentSessions.put(Thread.currentThread(), session );
localSessions.set(session);
}
// 3. 返回結(jié)果
return session;
// return sqlSessionFactory.openSession();
}
/**
* 回收資源方法. 避免關(guān)閉會(huì)話(huà)對(duì)象后,在集合中仍然有會(huì)話(huà)對(duì)象的引用. 造成過(guò)時(shí)對(duì)象的應(yīng)用.
*/
public static void close(){
SqlSession session = localSessions.get();
if(session != null){
session.close();
}
// 將關(guān)閉后的資源從集合中刪除
localSessions.remove();
}
}