成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

如何扒開 SqlSession 的外衣

運維 數據庫運維
如果我們配置的是MANAGED,會把事務交給容器來管理,比如JBOSS,Weblogic。因為我們是本地跑的程序,如果配置成MANAGED就會不有任何事務。

[[360740]]

老規矩,先上案例代碼,我們按照這個案例一步一步的搞定Mybatis源碼。

  1. public class MybatisApplication { 
  2.     public static final String URL = "jdbc:mysql://localhost:3306/mblog"
  3.     public static final String USER = "root"
  4.     public static final String PASSWORD = "123456"
  5.  
  6.     public static void main(String[] args) { 
  7.         String resource = "mybatis-config.xml"
  8.         InputStream inputStream = null
  9.         SqlSession sqlSession = null
  10.         try { 
  11.             inputStream = Resources.getResourceAsStream(resource); 
  12.             SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); 
  13.             sqlSession = sqlSessionFactory.openSession(); 
  14.             UserMapper userMapper = sqlSession.getMapper(UserMapper.class); 
  15.             System.out.println(userMapper.selectById(1)); 
  16.  
  17.         } catch (Exception e) { 
  18.             e.printStackTrace(); 
  19.         } finally { 
  20.             try { 
  21.                 inputStream.close(); 
  22.             } catch (IOException e) { 
  23.                 e.printStackTrace(); 
  24.             } 
  25.             sqlSession.close(); 
  26.         } 
  27.     } 

由于很多小伙伴在催,說Mybatis源碼系列好像何時才有下文了,為此老田熬夜寫了這篇。

 

繼續開擼~~

  1. SqlSession sqlSession = sqlSessionFactory.openSession(); 

前面那篇文章已經分析了,這里的sqlSessionFactory其實就是DefaultSqlSessionFactory。

所以這里,我們就從DefaultSqlSessionFactory里的openSession方法開始。

  1. public class DefaultSqlSessionFactory implements SqlSessionFactory { 
  2.  
  3.   private final Configuration configuration; 
  4.  
  5.   public DefaultSqlSessionFactory(Configuration configuration) { 
  6.     this.configuration = configuration; 
  7.   } 
  8.   //創建session,這個方法直接調用本類中的另外一個方法 
  9.   @Override 
  10.   public SqlSession openSession() { 
  11.     return openSessionFromDataSource(configuration.getDefaultExecutorType(), nullfalse); 
  12.   } 
  13.   //其實是調用這個方法 
  14.   private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) { 
  15.     Transaction tx = null
  16.     try { 
  17.       //對應xml標簽<environments> ,這個在配置文件解析的時候就已經存放到configuration中了。 
  18.       final Environment environment = configuration.getEnvironment(); 
  19.       final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment); 
  20.       tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit); 
  21.       //創建一個executor來執行SQL   
  22.       final Executor executor = configuration.newExecutor(tx, execType); 
  23.       //這里也說明了,為什么我們代碼里的SqlSession是DefaultSqlSession 
  24.       return new DefaultSqlSession(configuration, executor, autoCommit); 
  25.     } catch (Exception e) { 
  26.       closeTransaction(tx); // may have fetched a connection so lets call close() 
  27.       throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e); 
  28.     } finally { 
  29.       ErrorContext.instance().reset(); 
  30.     } 
  31.   } 
  32.    
  33.     private TransactionFactory getTransactionFactoryFromEnvironment(Environment environment) { 
  34.     if (environment == null || environment.getTransactionFactory() == null) { 
  35.       return new ManagedTransactionFactory(); 
  36.     } 
  37.     return environment.getTransactionFactory(); 
  38.   } 

這個方法中的主要內容有:

 

下面我們就來逐個攻破。

創建事務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。

  1. final Executor executor = configuration.newExecutor(tx, execType); 
  2. //Configuration中 
  3. public Executor newExecutor(Transaction transaction, ExecutorType executorType) { 
  4.     executorType = executorType == null ? defaultExecutorType : executorType; 
  5.     executorType = executorType == null ? ExecutorType.SIMPLE : executorType; 
  6.     Executor executor; 
  7.     //第一步 
  8.     if (ExecutorType.BATCH == executorType) { 
  9.       executor = new BatchExecutor(this, transaction); 
  10.     } else if (ExecutorType.REUSE == executorType) { 
  11.       executor = new ReuseExecutor(this, transaction); 
  12.     } else { 
  13.       executor = new SimpleExecutor(this, transaction); 
  14.     } 
  15.     //第二步 
  16.     if (cacheEnabled) { 
  17.       executor = new CachingExecutor(executor); 
  18.     } 
  19.     //第三步 
  20.     executor = (Executor) interceptorChain.pluginAll(executor); 
  21.     return executor; 
  22.   } 

此方法分三個步驟。

第一步:創建執行器

Executor的基本類型有三種:

  1. public enum ExecutorType { 
  2.   SIMPLE, REUSE, BATCH 

SIMPLE為默認類型。

 

為什么要讓抽象類BaseExecutor實現Executor接口,然后讓具體實現類繼承抽象類呢?

這就是模板方法模式的實現。

模板方法模式就是定義一個算法骨架,并允許子類為一個或者多個步驟提供實現。模板方法是得子類可以再不改變算法結構的情況下,重新定義算法的某些步驟。

抽象方法是在子類匯總實現的,每種執行器自己實現自己的邏輯,BaseExecutor最終會調用到具體的子類中。

抽象方法

  1. protected abstract int doUpdate(MappedStatement ms, Object parameter) throws SQLException; 
  2.  
  3. protected abstract List<BatchResult> doFlushStatements(boolean isRollback) throws SQLException; 
  4.  
  5. protected abstract <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException; 
  6.  
  7. protected abstract <E> Cursor<E> doQueryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds, BoundSql boundSql)  throws SQLException; 

第二步:緩存裝飾

在上面代碼中的第二步

  1. if (cacheEnabled) { 
  2.       executor = new CachingExecutor(executor); 

如果cacheEnabled=true,會用裝飾器設計模式對Executor進行裝飾。

第三步:插件代理緩存裝飾完后,就會執行

  1. executor = (Executor) interceptorChain.pluginAll(executor); 

這里會對Executor植入插件邏輯。

比如:分頁插件中就需要把插件植入的Executor

 

好了,到此,執行器創建的就搞定了。

創建DefaultSqlSession對象

把前面解析配置文件創建的Configuration對象和創建的執行器Executor賦給DefaultSqlSession中的屬性。

  1. public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) { 
  2.   this.configuration = configuration; 
  3.   this.executor = executor; 
  4.   this.dirty = false
  5.   this.autoCommit = autoCommit; 

到這里,SqlSession(DefaultSqlSession)對象就創建完畢。

總結

本文我們講了如何創建SqlSession的幾個步驟,最后我們獲得一個DefaultSqlSession對象,里面包含了執行器Executor和配置對象Configuration。Executor是SQL的實際執行對象。Configuration里保存著配置文件內容。

本文源碼分析的整個流程如下圖:

本文轉載自微信公眾號「Java后端技術全棧」,可以通過以下二維碼關注。轉載本文請聯系Java后端技術全棧公眾號。

 

責任編輯:武曉燕 來源: Java后端技術全棧
相關推薦

2025-04-28 01:22:45

2018-12-29 16:40:29

c語言編程語言指針

2021-05-25 07:59:59

Linux運維Linux系統

2012-08-30 09:17:28

Win 7Win 8操作系統

2021-08-10 12:05:19

Linuxworkqueue內核

2021-03-28 20:44:34

Kafka中間件MQ

2015-11-02 16:42:26

2020-12-01 10:27:39

區塊鏈比特幣

2010-06-29 16:36:27

間諜木馬惡意程序卡巴斯基

2013-10-10 09:24:34

2020-12-09 09:22:53

GETPOSTWeb

2023-08-14 07:19:23

2009-05-27 08:44:24

2017-09-07 07:20:10

2014-11-13 17:48:21

2020-02-06 10:20:19

硬件黑客技術

2012-09-06 09:57:34

Saas云安全云計算

2018-02-26 12:55:00

2022-11-26 10:14:48

Zookeepermybatisspring

2022-11-15 07:35:50

Spring事件觀察者模式
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲国产精品一区二区第一页 | 精品国产一区二区国模嫣然 | 亚洲啪啪| 成人国产精品久久 | 亚洲视频国产 | 欧美激情精品久久久久久 | 成人精品视频在线 | 国产精品1| 日韩欧美精品一区 | 日本不卡一区二区三区在线观看 | 成人黄色电影免费 | 欧美日韩国产在线观看 | 国内在线视频 | 免费成人国产 | 日本福利视频免费观看 | 国产精品视频一区二区三区 | 黄色三级免费网站 | 天天躁日日躁狠狠的躁天龙影院 | 国产丝袜一区二区三区免费视频 | 国产性色视频 | 在线观看视频一区二区三区 | 国产精品久久久久久久一区二区 | 精品一区二区三区视频在线观看 | 国产免费国产 | 中文字幕国产 | 欧美福利一区 | 亚洲免费精品 | 丁香婷婷成人 | 色综合色综合 | 国产在线观看一区二区 | 天天干视频 | 五月综合色啪 | 亚洲成人免费电影 | 精品国产91久久久久久 | 国产成人精品久久二区二区 | 狠狠影院 | 天天看片天天干 | www.国产91 | 电影在线| 老牛影视av一区二区在线观看 | 毛片免费观看视频 |