溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession作用域(Scope)和生命周期

發(fā)布時(shí)間:2020-07-16 01:50:25 來源:網(wǎng)絡(luò) 閱讀:487 作者:zsdnr 欄目:開發(fā)技術(shù)

可以說每個(gè)MyBatis都是以一個(gè)SqlSessionFactory實(shí)例為中心的。SqlSessionFactory實(shí)例可以通過SqlSessionFactoryBuilder來構(gòu)建。一是可以通過XML配置文件的方式來構(gòu)建SqlSessionFactory,二是可以通過Java API的方式來構(gòu)建。但不管通過什么方式都有一個(gè)Configuration貫穿始終,各種配置正是通過Configuration實(shí)例來完成實(shí)現(xiàn)。

此篇文章旨在通過編碼實(shí)現(xiàn)MyBatis3.4.1 User Guide所提到的作用域和生命周期指導(dǎo)建議。為什么要了解作用域和生命周期呢?在作用域內(nèi)正確地使用SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession會(huì)讓我們避免多線程環(huán)境下并發(fā)所帶來的問題。當(dāng)然如果使用依賴(DI)注入框架(Spring)可不用在代碼中關(guān)心作用域問題,因?yàn)橐蕾囎⑷肟蚣軙?huì)為我們做好幾乎一切工作。

首先我們來看User Guide對(duì)SqlSessionFactoryBuilder作用域以及生命周期的指導(dǎo)意見。

SqlSessionFactoryBuilder

這個(gè)類可以被實(shí)例化、使用和丟棄,一旦創(chuàng)建了 SqlSessionFactory,就不再需要它了。因此 SqlSessionFactoryBuilder 實(shí)例的最佳范圍是方法范圍(也就是局部方法變量)。你可以重用 SqlSessionFactoryBuilder 來創(chuàng)建多個(gè) SqlSessionFactory 實(shí)例,但是最好還是不要讓其一直存在以保證所有的 XML 解析資源開放給更重要的事情。

SqlSessionFactory

SqlSessionFactory 一旦被創(chuàng)建就應(yīng)該在應(yīng)用的運(yùn)行期間一直存在,沒有任何理由對(duì)它進(jìn)行清除或重建。使用 SqlSessionFactory 的最佳實(shí)踐是在應(yīng)用運(yùn)行期間不要重復(fù)創(chuàng)建多次,多次重建 SqlSessionFactory 被視為一種代碼“壞味道(bad smell)”。因此 SqlSessionFactory 的最佳范圍是應(yīng)用范圍。有很多方法可以做到,最簡(jiǎn)單的就是使用單例模式或者靜態(tài)單例模式。

SqlSession

每個(gè)線程都應(yīng)該有它自己的 SqlSession 實(shí)例。SqlSession 的實(shí)例不是線程安全的,因此是不能被共享的,所以它的最佳的范圍是請(qǐng)求或方法范圍。絕對(duì)不能將 SqlSession 實(shí)例的引用放在一個(gè)類的靜態(tài)域,甚至一個(gè)類的實(shí)例變量也不行。也絕不能將 SqlSession 實(shí)例的引用放在任何類型的管理范圍中,比如 Serlvet 架構(gòu)中的 HttpSession。如果你現(xiàn)在正在使用一種 Web 框架,要考慮 SqlSession 放在一個(gè)和 HTTP 請(qǐng)求對(duì)象相似的范圍中。換句話說,每次收到的 HTTP 請(qǐng)求,就可以打開一個(gè) SqlSession,返回一個(gè)響應(yīng),就關(guān)閉它。這個(gè)關(guān)閉操作是很重要的,你應(yīng)該把這個(gè)關(guān)閉操作放到 finally 塊中以確保每次都能執(zhí)行關(guān)閉。

通過User Guide可以看到官方對(duì)SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession的作用域范圍分別是:方法范圍、應(yīng)用范圍、請(qǐng)求或方法范圍。初學(xué)者很容易將SqlSessionFactory的作用域范圍忽略,而將其和SqlSessionFactoryBuilder和SqlSession都置于方法范圍內(nèi),這樣本身并不會(huì)帶來程序代碼錯(cuò)誤(只有在將SqlSession置于應(yīng)用范圍才會(huì)帶來并發(fā)性問題),然而這會(huì)被認(rèn)為是“bad smell”。我在第一篇寫《MyBatis3入門》時(shí),就沒有仔細(xì)閱讀User Guide以至于代碼聞起來有一種“壞味道(bad smell)”。例,代碼如下:

SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession作用域(Scope)和生命周期

1 public class SessionFactory {2     public static SqlSession getSqlSession(String resource) throws IOException{3         InputStream inputStream = Resources.getResourceAsStream(resource);4         SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);5         SqlSession sqlSession = sqlSessionFactory.openSession();6         7         return sqlSession;8     }9 }

SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession作用域(Scope)和生命周期

第4行的代碼聞起來就有一個(gè)“bad smell”的味道,因?yàn)樗淖饔貌皇窃谡麄€(gè)應(yīng)用范圍而是在方法范圍。

而什么是較好的代碼呢?我們應(yīng)該如上所說,對(duì)SqlSessionFactory使用單例模式。重構(gòu)后的代碼如下:

SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession作用域(Scope)和生命周期

 1 package day_8_mybatis.util; 2  3 import java.io.InputStream; 4  5 import org.apache.ibatis.session.SqlSessionFactory; 6 import org.apache.ibatis.session.SqlSessionFactoryBuilder; 7  8 /** 9  * @author turbo10  *11  * 2016年10月26日12  */13 public class SessionFactory2 {14     private static SqlSessionFactory sqlSessionFactory;15     16     public static synchronized SqlSessionFactory getInstance(InputStream inputStream){17         if (null == sqlSessionFactory){18             sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);19         }20         21         return sqlSessionFactory;22     }23 }

SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession作用域(Scope)和生命周期

客戶端創(chuàng)建SqlSession的代碼如下:

SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession作用域(Scope)和生命周期

 1 package day_8_mybatis; 2  3 import java.io.IOException; 4 import java.io.InputStream; 5  6 import org.apache.ibatis.io.Resources; 7 import org.apache.ibatis.session.SqlSession; 8  9 import day_8_mybatis.util.SessionFactory2;10 11 /**12  * 客戶端13  * 
14  * @author turbo15  *16  * 2016年10月26日17  */18 public class Main {19 20     /**21      * @param args22      * @throws IOException23      */24     public static void main(String[] args) throws Exception {25         String resource = "day_8_mybatis/mybatis-config.xml"; // 獲取mybatis配置文件路徑26         InputStream inputStream = Resources.getResourceAsStream(resource);27         SqlSession sqlSession = SessionFactory2.getInstance(inputStream).openSession();28 29     }30 31 }

SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession作用域(Scope)和生命周期

這樣的代碼是不是就符合標(biāo)準(zhǔn),并且看起來舒服多,漂亮多了?


向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI