SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession作用域(Scope)和生命周期
1、可以說每個MyBatis都是以一個SqlSessionFactory實例為中心的
SqlSessionFactory實例可以通過SqlSessionFactoryBuilder來構建。一是可以通過XML配置文件的方式來構建SqlSessionFactory,二是可以通過Java API的方式來構建。都有一個Configuration貫穿始終,各種配置正是通過Configuration實例來完成實現。
2、為什么要了解作用域和生命周期呢
在作用域內正確地使用SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession會讓我們避免多線程環境下並發所帶來的問題。當然如果使用依賴(DI)注入框架(Spring)可不用在代碼中關心作用域問題,因為依賴注入框架會為我們做好幾乎一切工作。
3、SqlSessionFactoryBuilder
這個類可以被實例化、使用和丟棄,一旦創建了 SqlSessionFactory,就不再需要它了。因此 SqlSessionFactoryBuilder 實例的最佳范圍是
方法范圍(也就是局部方法變量)。你可以重用 SqlSessionFactoryBuilder 來創建多個 SqlSessionFactory 實例,但是最好還是不要讓其一直存在以保證所有的 XML 解析資源開放給更重要的事情。
4、SqlSessionFactory
SqlSessionFactory 一旦被創建就應該在應用的運行期間一直存在,沒有任何理由對它進行清除或重建。使用 SqlSessionFactory 的最佳實踐是在應用運行期間不要重復創建多次 。因此 SqlSessionFactory 的最佳范圍是
應用范圍。有很多方法可以做到,最簡單的就是使用單例模式或者靜態單例模式。
5、SqlSession
每個線程都應該有它自己的 SqlSession 實例。SqlSession 的實例不是線程安全的,因此是不能被共享的,所以它的最佳的范圍是
請求或方法范圍。絕對不能將 SqlSession 實例的引用放在一個類的靜態域,甚至一個類的實例變量也不行。也絕不能將 SqlSession 實例的引用放在任何類型的管理范圍中,比如 Serlvet 架構中的 HttpSession。如果你現在正在使用一種 Web 框架,要考慮 SqlSession 放在一個和 HTTP 請求對象相似的范圍中。換句話說,每次收到的 HTTP 請求,就可以打開一個 SqlSession,返回一個響應,就關閉它。這個關閉操作是很重要的,你應該把這個關閉操作放到 finally 塊中以確保每次都能執行關閉。
6、總結
通過User Guide可以看到官方對SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession的作用域范圍分別是:方法范圍、應用范圍、請求或方法范圍。初學者很容易將SqlSessionFactory的作用域范圍忽略,而將其和SqlSessionFactoryBuilder和SqlSession都置於方法范圍內,這樣本身並不會帶來程序代碼錯誤(只有在將SqlSession置於應用范圍才會帶來並發性問題)。