1. 程式人生 > >Mybatis中SqlSessionFactoryBuilder/SqlSessionFactory/SqlSession/對映器例項的作用域(Scope)和生命週期

Mybatis中SqlSessionFactoryBuilder/SqlSessionFactory/SqlSession/對映器例項的作用域(Scope)和生命週期

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

SqlSessionFactory

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

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

複製程式碼

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

複製程式碼

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

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

複製程式碼

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

複製程式碼