1. 程式人生 > >[MyBatis] 主要類的作用域和生命週期

[MyBatis] 主要類的作用域和生命週期

主要類的作用域和生命週期

  • SqlSessionFactoryBuilder
  • SqlSessionFactory
  • SqlSession
  • 對映器例項(Mapper Instances)

理解以上類的不同作用域和生命週期類是至關重要的,因為錯誤的使用會導致非常嚴重的併發問題

SqlSessionFactoryBuilder

這個類可以被例項化、使用和丟棄,一旦建立了SqlSessionFactory,就不再需要它了。因此SqlSessionFactoryBuilder例項的最佳作用域是方法作用域(也就是區域性方法變數)。你可以重用SqlSessionFactoryBuilder來建立多個SqlSessionFactory例項,但是最好還是不要讓其一直存在以保證所有的XML解析資源開放給更重要的事情。

SqlSessionFactoy

SqlSessionFactoy 一旦被建立就應該在應用的執行期間一直存在,沒有任何理由對它進行清除或重建。使用SqlSessionFactory的最佳實踐是在應用執行期間不要重複建立多次,多次重建SqlSessionFactory被視為一種程式碼"壞味道"。因此SqlSessionFactoy的最佳作用域是應用作用域。有很多方法可以做到,最簡單的就是使用單例模式或者靜態單例模式。

SqlSession

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

SqlSession session = sqlSessionFactory.openSession();
try {
  // do work
} finally {
  session.close();
}

在你的所有的程式碼中一致性地使用這種模式來保證所有資料庫資源都能被正確地關閉。

對映器例項(Mapper Instances)

對映器是一個你建立來繫結你對映的語句的介面。對映器介面的例項是從 SqlSession 中獲得的。因此從技術層面講,任何對映器例項的最大作用域是和請求它們的 SqlSession 相同的。儘管如此,對映器例項的最佳作用域是方法作用域。也就是說,對映器例項應該在呼叫它們的方法中被請求,用過之後即可廢棄。並不需要顯式地關閉對映器例項,儘管在整個請求作用域(request scope)保持對映器例項也不會有什麼問題,但是很快你會發現,像 SqlSession 一樣,在這個作用域上管理太多的資源的話會難於控制。所以要保持簡單,最好把對映器放在方法作用域(method scope)內。下面的示例就展示了這個實踐:

SqlSession session = sqlSessionFactory.openSession();
try {
  BlogMapper mapper = session.getMapper(BlogMapper.class);
  // do work
} finally {
  session.close();
}