重溫Mybatis(二)---------核心類生命週期和作用域

  上一章搭建了一個簡單的mybatis應用,見到了mybatis的幾個核心類:SqlSessionFactoryBuilder SqlSessionFactory ,SqlSession,那麼這些對象什麼時候創建呢,在使用mybatis過程中,他們的最佳作用域是什麼呢?

SqlSessionFactoryBuilder

這個類可以被實例化、使用和丟棄,這個類的作用就是爲了創建SqlSessionFactory的,一旦SqlSessionFactory創建完畢,SqlSessionFactoryBuilder就沒有存在的價值了,就應該被銷燬。所以SqlSessionFactoryBuilder最好的作用域就是方法體內(及作爲一個本地方法變量),用完即銷燬。生命週期也就是調用方法的開始到結束。

SqlSessionFactory

SqlSessionFactory 一旦被創建就應該在應用的運行期間一直存在,沒有任何理由丟棄它或重新創建另一個實例。 使用 SqlSessionFactory 的最佳實踐是在應用運行期間不要重複創建多次,因此 SqlSessionFactory 的最佳作用域是應用作用域。 有很多方法可以做到,最簡單的就是使用單例模式或者靜態單例模式

SqlSession

SqlSession實例是不能共享的,並且不是現程安全的,所以它的最好的作用域應該是方法體內,或者是一次請求時,即method或者request,也就是說再收到一次Http請求時,就應該創建一次一個SqlSession實例,那麼也就是

說在每次使用完之後我們都需要把它關閉,即調用.close();
 

每個線程都應該有它自己的 SqlSession 實例。SqlSession 的實例不是線程安全的,因此是不能被共享的,所以它的最佳的作用域是請求或方法作用域絕對不能將 SqlSession 實例的引用放在一個類的靜態域,甚至一個類的實例變量也不行。 也絕不能將 SqlSession 實例的引用放在任何類型的託管作用域中,比如 Servlet 框架中的 HttpSession。 如果你現在正在使用一種 Web 框架,可以考慮將 SqlSession 放在一個和 HTTP 請求相似的作用域中。 換句話說,每次收到 HTTP 請求,就可以打開一個 SqlSession,返回一個響應後,就關閉它。 這個關閉操作很重要,爲了確保每次都能執行關閉操作,你應該把這個關閉操作放到 finally 塊中。 下面的示例就是一個確保 SqlSession 關閉的標準模式:

try (SqlSession session = sqlSessionFactory.openSession()) {
  // 你的應用邏輯代碼
}finally{
    session.close();
}

在所有代碼中都遵循這種使用模式,可以保證所有數據庫資源都能被正確地關閉。

映射器實例

映射器是一些綁定映射語句的接口。映射器接口的實例是從 SqlSession 中獲得的。雖然從技術層面上來講,任何映射器實例的最大作用域與請求它們的 SqlSession 相同。但方法作用域纔是映射器實例的最合適的作用域。 也就是說,映射器實例應該在調用它們的方法中被獲取,使用完畢之後即可丟棄。 映射器實例並不需要被顯式地關閉。儘管在整個請求作用域保留映射器實例不會有什麼問題,但是你很快會發現,在這個作用域上管理太多像 SqlSession 的資源會讓你忙不過來。 因此,最好將映射器放在方法作用域內。就像下面的例子一樣:

try (SqlSession session = sqlSessionFactory.openSession()) {
  BlogMapper mapper = session.getMapper(BlogMapper.class);
  // 你的應用邏輯代碼
}

下面是一些代碼片段,讓我們更好的來理解mybatis這些核心類的作用域。

String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sqlSessionFactory.openSession();

這段代碼,雖然能滿足功能上的實現,但是,第三行代碼獲取SqlSessionFactory方法作用域並沒有放到整個應用範圍,而是方法範圍,背離了官方的建議,優化後的代碼如下:

 
 public class SessionFactory2 {
     private static SqlSessionFactory sqlSessionFactory;
     
     public static synchronized SqlSessionFactory getInstance(InputStream inputStream){
         if (null == sqlSessionFactory){
             sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
         }
         
         return sqlSessionFactory;
     }
 }
public class Main {
    public static void main(String[] args) throws Exception {
        String resource = "day_8_mybatis/mybatis-config.xml"; // 獲取mybatis配置文件路徑
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSession sqlSession = SessionFactory2.getInstance(inputStream).openSession();

     }
 
 }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章