共計 5387 個字符,預計需要花費 14 分鐘才能閱讀完成。
這篇文章主要介紹“如何理解 SqlSession 技術”,在日常操作中,相信很多人在如何理解 SqlSession 技術問題上存在疑惑,丸趣 TV 小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”如何理解 SqlSession 技術”的疑惑有所幫助!接下來,請跟著丸趣 TV 小編一起來學習吧!
老規矩,先上案例代碼,我們按照這個案例一步一步的搞定 Mybatis 源碼。
public class MybatisApplication { public static final String URL = jdbc:mysql://localhost:3306/mblog public static final String USER = root public static final String PASSWORD = 123456 public static void main(String[] args) { String resource = mybatis-config.xml InputStream inputStream = null; SqlSession sqlSession = null; try { inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); sqlSession = sqlSessionFactory.openSession(); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); System.out.println(userMapper.selectById(1)); } catch (Exception e) { e.printStackTrace(); } finally { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } sqlSession.close(); } }
由于很多小伙伴在催,說 Mybatis 源碼系列好像何時才有下文了,為此老田熬夜寫了這篇。
繼續開擼~~
SqlSession sqlSession = sqlSessionFactory.openSession();
前面那篇文章已經分析了,這里的 sqlSessionFactory 其實就是 DefaultSqlSessionFactory。
所以這里,我們就從 DefaultSqlSessionFactory 里的 openSession 方法開始。
public class DefaultSqlSessionFactory implements SqlSessionFactory { private final Configuration configuration; public DefaultSqlSessionFactory(Configuration configuration) { this.configuration = configuration; } // 創建 session,這個方法直接調用本類中的另外一個方法 @Override public SqlSession openSession() { return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false); } // 其實是調用這個方法 private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) { Transaction tx = null; try { // 對應 xml 標簽 environments , 這個在配置文件解析的時候就已經存放到 configuration 中了。 final Environment environment = configuration.getEnvironment(); final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment); tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit); // 創建一個 executor 來執行 SQL final Executor executor = configuration.newExecutor(tx, execType); // 這里也說明了,為什么我們代碼里的 SqlSession 是 DefaultSqlSession return new DefaultSqlSession(configuration, executor, autoCommit); } catch (Exception e) { closeTransaction(tx); // may have fetched a connection so lets call close() throw ExceptionFactory.wrapException( Error opening session. Cause: + e, e); } finally { ErrorContext.instance().reset(); } } private TransactionFactory getTransactionFactoryFromEnvironment(Environment environment) { if (environment == null || environment.getTransactionFactory() == null) { return new ManagedTransactionFactory(); } return environment.getTransactionFactory(); }
這個方法中的主要內容有:
下面我們就來逐個攻破。
創建事務 Transaction
事務工廠類型可以配置為 JDBC 類型或者 MANAGED 類型。
JdbcTransactionFactory 生產 JdbcTransaction。
ManagedTransactionFactory 生產 ManagedTransaction。
如果配置的 JDBC,則會使用 Connection 對象的 commit()、rollback()、close() 方法來管理事務。
如果我們配置的是 MANAGED,會把事務交給容器來管理,比如 JBOSS,Weblogic。因為我們是本地跑的程序,如果配置成 MANAGED 就會不有任何事務。
但是,如果我們項目中是 Spring 集成 Mybatis,則沒有必要配置事務,因為我們會直接在 applicationContext.xml 里配置數據源和事務管理器,從而覆蓋 Mybatis 的配置。
創建執行器 Executor
調用 configuration 的 newExecutor 方法創建 Executor。
final Executor executor = configuration.newExecutor(tx, execType); //Configuration 中 public Executor newExecutor(Transaction transaction, ExecutorType executorType) { executorType = executorType == null ? defaultExecutorType : executorType; executorType = executorType == null ? ExecutorType.SIMPLE : executorType; Executor executor; // 第一步 if (ExecutorType.BATCH == executorType) { executor = new BatchExecutor(this, transaction); } else if (ExecutorType.REUSE == executorType) { executor = new ReuseExecutor(this, transaction); } else { executor = new SimpleExecutor(this, transaction); } // 第二步 if (cacheEnabled) { executor = new CachingExecutor(executor); }
// 第三步 executor = (Executor) interceptorChain.pluginAll(executor);
return executor; }
此方法分三個步驟。
第一步:創建執行器
Executor 的基本類型有三種:
public enum ExecutorType { SIMPLE, REUSE, BATCH }
SIMPLE 為默認類型。
為什么要讓抽象類 BaseExecutor 實現 Executor 接口,然后讓具體實現類繼承抽象類呢?
這就是模板方法模式的實現。
模板方法模式就是定義一個算法骨架,并允許子類為一個或者多個步驟提供實現。模板方法是得子類可以再不改變算法結構的情況下,重新定義算法的某些步驟。
抽象方法是在子類匯總實現的,每種執行器自己實現自己的邏輯,BaseExecutor 最終會調用到具體的子類中。
抽象方法
protected abstract int doUpdate(MappedStatement ms, Object parameter) throws SQLException; protected abstract List BatchResult doFlushStatements(boolean isRollback) throws SQLException; protected abstract E List E doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException; protected abstract E Cursor E doQueryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds, BoundSql boundSql) throws SQLException;
第二步:緩存裝飾
在上面代碼中的第二步
if (cacheEnabled) { executor = new CachingExecutor(executor); }
如果 cacheEnabled=true,會用裝飾器設計模式對 Executor 進行裝飾。
第三步:插件代理緩存裝飾完后,就會執行
executor = (Executor) interceptorChain.pluginAll(executor);
這里會對 Executor 植入插件邏輯。
比如:分頁插件中就需要把插件植入的 Executor
好了,到此,執行器創建的就搞定了。
創建 DefaultSqlSession 對象
把前面解析配置文件創建的 Configuration 對象和創建的執行器 Executor 賦給 DefaultSqlSession 中的屬性。
public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) { this.configuration = configuration; this.executor = executor; this.dirty = false; this.autoCommit = autoCommit; }
到這里,SqlSession(DefaultSqlSession) 對象就創建完畢。
到此,關于“如何理解 SqlSession 技術”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注丸趣 TV 網站,丸趣 TV 小編會繼續努力為大家帶來更多實用的文章!