本文收錄於模仿與學習MyBatis系列
簡述
在前一章《模仿與學習MyBatis - 1.3 xml配置的解析》中,對指定的文件實行了一個基本的DataSource解析類
XMLConfigBuilder
。在本篇中將討論以及實現一個最基本的
SessionFactory
(關於Session的意義可跳轉到這裏)。計劃未來所有Session,都統一通過SessionFactory.openSession()
這類方式獲取。
最終項目是一個Java Maven項目,代碼存在github了。
SessionFactory的意義
首先我們來觀察一下SessionFactory在MyBatis中是怎樣的:
public interface SqlSessionFactory {
SqlSession openSession();
SqlSession openSession(boolean autoCommit);
SqlSession openSession(Connection connection);
SqlSession openSession(TransactionIsolationLevel level);
SqlSession openSession(ExecutorType execType);
SqlSession openSession(ExecutorType execType, boolean autoCommit);
SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level);
SqlSession openSession(ExecutorType execType, Connection connection);
Configuration getConfiguration();
}
- 可以看到這個接口定義了非常多方法,但主要的目的,無非就是爲了獲取一個Session。根據設計模式的角度來看,SessionFactory是Session的工廠,即是負責吐出Session的類。實現不同的SessionFactory,以及有着不同的配置方式(xml配置、Spring對接等等),而實現不同的Session有不同的執行效果。這樣框架的配置與功能就分開了,這樣我們可以方便的搭配與組合。這一處也正是解耦與工廠模式的意義。
- 另外,Session中的緩存就是俗稱的一級緩存,通過一個Session查詢的值(如果中間未修改的話)可以直接從緩存中讀取到,不用每次都從數據庫中查詢同樣的東西。那麼問題來了,如果有些值查詢特別頻繁,我們希望有一個,對所有Session查詢都有效的全局緩存,要怎麼辦呢?這時候SessionFactory的作用又體現出來了,通常全局緩存(也稱爲二級緩存)就是與SessionFactory相關的。這裏暫時不作展開,因爲在後續改進版當中會用到緩存。
- 還有第三個用處,在MyBatis中並不有效。有的框架,新建Session代價較大,不希望頻繁的創建銷燬,而是希望對應一個線程分配一個Session。這時線程獨立的Session,通常只能在SessionFactory這個全局唯一的factory上進行分配。
綜上所述,暫時我們只需要考慮第一點就足夠了。
SessionFactory的實現
在本章節,將利用上一章實現的XMLConfigBuilder
,完成一個基本功能。先構造一個標準的SessionFactory接口:
public interface SessionFactory {
Session openSession();
}
利用XMLConfigBuilder
只要簡單的把文件名傳給它,吐出一個DataSource
,存下,在openSession時帶入即可 :
public class VSessionFactory implements SessionFactory {
private DataSource config;
public VSessionFactory(String resource) {
config = XMLConfigBuilder.build(resource);
}
public Session openSession() {
return new VSession(config);
}
}
最後還是慣例,上一段測試代碼。
public static void main(String args[]) throws Exception {
SessionFactory factory = new VSessionFactory("config.xml");
Session session = factory.openSession();
session.exec("select * from article where id<30");
}
結果沒有任何問題:
--------------------print--------------------
id=1
title=歡迎來到自由茶社
brief=這裏是大門的入口
content=這裏是大門的入口
father_id=0
author_name=me
create_time=2016-11-16 23:44:36.0
modify_time=2016-12-06 00:41:07.0
id=29
title=第一章
brief=隨便打的內容
content=隨便打的內容
father_id=1
author_name=me
create_time=2016-11-16 23:45:20.0
modify_time=2016-11-16 23:45:20.0
以上。