最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Mybatis SqlSessionFactory與SqlSession詳細講解

 更新時間:2022年11月18日 11:17:11   作者:氵奄不死的魚  
SqlSessionFactory是MyBatis的核心類之一,其最重要的功能就是提供創(chuàng)建MyBatis的核心接口SqlSession,所以我們需要先創(chuàng)建SqlSessionFactory,為此我們需要提供配置文件和相關(guān)的參數(shù)

SqlssionFactory

1.SqlSessionFactory是MyBatis的關(guān)鍵對象,它是個單個數(shù)據(jù)庫映射關(guān)系經(jīng)過編譯后的內(nèi)存鏡像。

2.SqlSessionFactory對象的實例可以通過SqlSessionFactoryBuilder對象類獲得,而SqlSessionFactoryBuilder則可以從XML配置文件或一個預(yù)先定制的Configuration的實例構(gòu)建出SqlSessionFactory的實例。

3.每一個MyBatis的應(yīng)用程序都以一個SqlSessionFactory對象的實例為核心。

4.SqlSessionFactory是線程安全的,SqlSessionFactory一旦被創(chuàng)建,應(yīng)該在應(yīng)用執(zhí)行期間都存在。在應(yīng)用運行期間不要重復(fù)創(chuàng)建多次,建議使用單例模式。

5.SqlSessionFactory是創(chuàng)建SqlSession的工廠。

SqlSessionFactory接口源碼如下所示

package org.apache.ibatis.session; 
import java.sql.Connection; 
public interface SqlSessionFactory { 
  SqlSession openSession();//這個方法最經(jīng)常用,用來創(chuàng)建SqlSession對象。
  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(); 
}

創(chuàng)建SqlSessionFactory

.mybatis框架主要是圍繞著SqlSessionFactory進行的,創(chuàng)建過程大概如下:

就從mybatis默認實現(xiàn)的MybatisAutoConfiguration來看看

 @Bean
  @ConditionalOnMissingBean
  public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
    //創(chuàng)建SqlSessionFactoryBean對象
     SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
      //設(shè)置數(shù)據(jù)源
    factory.setDataSource(dataSource);
    factory.setVfs(SpringBootVFS.class);
    if (StringUtils.hasText(this.properties.getConfigLocation())) {
     //mybatis ,Xml配置文件路徑
        、factory.setConfigLocation(this.resourceLoader.getResource(this.properties.getConfigLocation()));
    }
      //應(yīng)用配置文件
    applyConfiguration(factory);
      //Mybatis額外的配置文件
    if (this.properties.getConfigurationProperties() != null) {
      factory.setConfigurationProperties(this.properties.getConfigurationProperties());
    }
      //設(shè)置mybatis攔截器
    if (!ObjectUtils.isEmpty(this.interceptors)) {
      factory.setPlugins(this.interceptors);
    }
    ···
      //設(shè)置*mapper.xml掃描路徑
    if (!ObjectUtils.isEmpty(this.properties.resolveMapperLocations())) {
      factory.setMapperLocations(this.properties.resolveMapperLocations());
    }
    ····	
        //獲取創(chuàng)建SqlSessionFactoryBean對象
    return factory.getObject();
  }

經(jīng)過一系列設(shè)置創(chuàng)建出SqlSessionFactory

注意僅有當數(shù)據(jù)源只有一個實現(xiàn)時,MybatisAutoConfiguration才會生效,如果時多數(shù)據(jù)源的情況下,那么需要自己編寫定義SqlSessionFactory的創(chuàng)建邏輯

SqlSessionTemplate

SqlSessionTemplate是線程安全的,生命周期由spring管理的,同spring事務(wù)一起協(xié)作來保證真正執(zhí)行的SqlSession是在spring的事務(wù)中的一個SqlSession的實現(xiàn)類

創(chuàng)建SqlSessionTemplate

@Bean
  @ConditionalOnMissingBean
  public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
    ExecutorType executorType = this.properties.getExecutorType();
    if (executorType != null) {
      return new SqlSessionTemplate(sqlSessionFactory, executorType);
    } else {
      return new SqlSessionTemplate(sqlSessionFactory);
    }
  }

SqlSessionTemplate是作為一個bean被spring管理的

  public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType,
      PersistenceExceptionTranslator exceptionTranslator) {
    notNull(sqlSessionFactory, "Property 'sqlSessionFactory' is required");
    notNull(executorType, "Property 'executorType' is required");
    this.sqlSessionFactory = sqlSessionFactory;
    this.executorType = executorType;
    this.exceptionTranslator = exceptionTranslator;
    this.sqlSessionProxy = (SqlSession) newProxyInstance(SqlSessionFactory.class.getClassLoader(),
        new Class[] { SqlSession.class }, new SqlSessionInterceptor());
  }

內(nèi)部的sqlSessionProxy是對sqlSession做的代理

處理類是SqlSessionInterceptor

SqlSessionTemplate繼承自SqlSession,實現(xiàn)了sqlSession的所有操作

 @Override
  public int insert(String statement, Object parameter) {
    return this.sqlSessionProxy.insert(statement, parameter);
  }
·········

可以看出來,SqlSessionTemplate就是對SqlSession套了個殼子,具體實現(xiàn)還是有代理的sqlSessionProxy去執(zhí)行

接下類進入

SqlSessionInterceptor

 @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      SqlSession sqlSession = getSqlSession(SqlSessionTemplate.this.sqlSessionFactory,
          SqlSessionTemplate.this.executorType, SqlSessionTemplate.this.exceptionTranslator);
      try {
        Object result = method.invoke(sqlSession, args);
        if (!isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) {
          // force commit even on non-dirty sessions because some databases require
          // a commit/rollback before calling close()
          sqlSession.commit(true);
        }
        return result;
      } 
  }

先獲取一個sqlSession,這里也是sqlSession線程安全的原因

getSqlSession方法拿到DefaultSqlSession實例,getSqlSession方法里面處理了sqlSession的線程安全問題(通過ThreadLocal實現(xiàn))。

 SqlSessionHolder holder = (SqlSessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
    SqlSession session = sessionHolder(executorType, holder);
    if (session != null) {
      return session;
    }
    LOGGER.debug(() -> "Creating a new SqlSession");
    session = sessionFactory.openSession(executorType);
    registerSessionHolder(sessionFactory, executorType, exceptionTranslator, session);

sqlSession與線程綁定,如果當前線程未綁定sqlSession,會創(chuàng)建并綁定。保證了一個sqlSession一定只能被一個線程使用。

另外如果在一個事務(wù)下,那么肯定是在同一個線程,事務(wù)內(nèi)的操作會共用一個sqlSession,并且,每一步操作完畢之后不會自動提交事務(wù)。

SqlSession

1.SqlSession是MyBatis的關(guān)鍵對象,是執(zhí)行持久化操作的獨享,類似于JDBC中的Connection。

2.它是應(yīng)用程序與持久層之間執(zhí)行交互操作的一個單線程對象,也是MyBatis執(zhí)行持久化操作的關(guān)鍵對象。

3.SqlSession對象完全包含以數(shù)據(jù)庫為背景的所有執(zhí)行SQL操作的方法,它的底層封裝了JDBC連接,可以用SqlSession實例來直接執(zhí)行被映射的SQL語句。

4.每個線程都應(yīng)該有它自己的SqlSession實例。

5.SqlSession的實例不能被共享,同時SqlSession也是線程不安全的,絕對不能講SqlSeesion實例的引用放在一個類的靜態(tài)字段甚至是實例字段中。也絕不能將SqlSession實例的引用放在任何類型的管理范圍中,比如Servlet當中的HttpSession對象中。

6.使用完SqlSeesion之后關(guān)閉Session很重要,應(yīng)該確保使用finally塊來關(guān)閉它。

package org.apache.ibatis.session; 
import java.io.Closeable; 
import java.sql.Connection; 
import java.util.List; 
import java.util.Map; 
import org.apache.ibatis.executor.BatchResult; 
public interface SqlSession extends Closeable { 
  <T> T selectOne(String statement); 
  <T> T selectOne(String statement, Object parameter); 
  <E> List<E> selectList(String statement); 
  <E> List<E> selectList(String statement, Object parameter); 
  <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds); 
  <K, V> Map<K, V> selectMap(String statement, String mapKey); 
  <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey); 
  <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds); 
  void select(String statement, Object parameter, ResultHandler handler); 
  void select(String statement, ResultHandler handler); 
  void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler); 
  int insert(String statement); 
  int insert(String statement, Object parameter); 
  int update(String statement); 
  int update(String statement, Object parameter); 
  int delete(String statement); 
  int delete(String statement, Object parameter); 
  void commit(); void commit(boolean force); 
  void rollback(); 
  void rollback(boolean force); 
  List<BatchResult> flushStatements(); 
  void close(); 
  void clearCache(); 
  Configuration getConfiguration(); 
  <T> T getMapper(Class<T> type); 
  Connection getConnection(); 
}

創(chuàng)建一個SqlSession

看了前面我們知道了sqlSession通過SqlSessionTemplate進行創(chuàng)建的

org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#openSessionFromDataSource

 private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
    Transaction tx = null;
    try {
      final Environment environment = configuration.getEnvironment();
      final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
      tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
      final Executor executor = configuration.newExecutor(tx, execType);
      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();
    }
  }

創(chuàng)建一個事務(wù),創(chuàng)建一個Executor,構(gòu)造DefaultSqlSession

  public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) {
    this.configuration = configuration;
    this.executor = executor;
    this.dirty = false;
    this.autoCommit = autoCommit;
  }

dirty字段代表如果在在未提交之前有更新操作,會被更新未true,這時調(diào)用sqlSession的commit/rollbacl方法

調(diào)用 executor.commit都傳的是true

@Override
  public void commit(boolean force) {
    try {
      executor.commit(isCommitOrRollbackRequired(force));
      dirty = false;
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error committing transaction.  Cause: " + e, e);
    } finally {
      ErrorContext.instance().reset();
    }
  }

后續(xù)sqlSession的增刪改查操作都通過executor完成,executor后面再繼續(xù)研究

SqlSession生命周期

如果說SqlSessionFactory相當于數(shù)據(jù)庫連接池,那么SqlSession就相當于一個數(shù)據(jù)庫連接(Connection對象),

你可以在一個事務(wù)里面執(zhí)行多條SQL,然后通過它的commit、rollback等方法,提交或者回滾事務(wù)。所以它應(yīng)該存活在一個業(yè)務(wù)請求中,

處理完整個請求后,應(yīng)該關(guān)閉這條連接,讓它歸還給SqlSessionFactory,否則數(shù)據(jù)庫資源就很快被消耗精光,系統(tǒng)應(yīng)付癱瘓,所以用try…catch…fanally語句來保證其正確關(guān)閉。

實際上MyBatis整合springBoot的情況下,SqlSession對象和線程進行綁定,對象本身可以循環(huán)被一個線程反復(fù)使用,但是依然保證了線程安全,在事務(wù)提交/回滾需要清理緩存,交換連接給數(shù)據(jù)庫連接池

到此這篇關(guān)于Mybatis SqlSessionFactory與SqlSession詳細講解的文章就介紹到這了,更多相關(guān)Mybatis SqlSessionFactory內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java常用命令匯總

    Java常用命令匯總

    這篇文章主要介紹了Java常用命令匯總,小編覺得挺不錯的,這里給大家分享下,供需要的朋友參考。
    2017-10-10
  • java實現(xiàn)多選批量刪除功能

    java實現(xiàn)多選批量刪除功能

    工作中批量刪除可以提高我們的工作效率,今天這篇文章主要介紹了java實現(xiàn)多選批量刪除功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • java并發(fā)編程死鎖定義及如何避免死鎖

    java并發(fā)編程死鎖定義及如何避免死鎖

    這篇文章主要為大家介紹了java并發(fā)編程中死鎖的詳細說明及如何避免死鎖的方法,有需要的朋友可以借鑒參考下希望能夠有所幫助,祝大家多多進步
    2022-02-02
  • java線性表排序示例分享

    java線性表排序示例分享

    這篇文章主要介紹了java線性表排序示例,需要的朋友可以參考下
    2014-03-03
  • java多線程編程之Synchronized關(guān)鍵字詳解

    java多線程編程之Synchronized關(guān)鍵字詳解

    這篇文章主要為大家詳細介紹了java多線程編程之Synchronized關(guān)鍵字,感興趣的朋友可以參考一下
    2016-05-05
  • java在hashmap初始化時賦初值過程解析

    java在hashmap初始化時賦初值過程解析

    這篇文章主要介紹了java在hashmap初始化時賦初值過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-10-10
  • 多線程下怎樣保證OkHttpClient的線程安全

    多線程下怎樣保證OkHttpClient的線程安全

    這篇文章主要介紹了多線程下怎樣保證OkHttpClient的線程安全問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • 教你用Java實現(xiàn)一個簡單的代碼生成器

    教你用Java實現(xiàn)一個簡單的代碼生成器

    今天給大家?guī)淼氖顷P(guān)于Java的相關(guān)知識,文章圍繞著如何用Java實現(xiàn)一個簡單的代碼生成器展開,文中有非常詳細的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • Java實現(xiàn)AES加密算法的簡單示例分享

    Java實現(xiàn)AES加密算法的簡單示例分享

    這篇文章主要介紹了Java實現(xiàn)AES加密算法的簡單示例分享,AES算法是基于對密碼值的置換和替代,需要的朋友可以參考下
    2016-04-04
  • spring?boot集成WebSocket日志實時輸出到web頁面

    spring?boot集成WebSocket日志實時輸出到web頁面

    這篇文章主要為大家介紹了spring?boot集成WebSocket日志實時輸出到web頁面展示的詳細操作,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步
    2022-03-03

最新評論

九江市| 镇赉县| 光山县| 本溪市| 南京市| 博湖县| 阜宁县| 正定县| 余姚市| 辽中县| 穆棱市| 乡城县| 德州市| 隆回县| 商水县| 云霄县| 文水县| 搜索| 紫云| 剑河县| 揭西县| 中方县| 繁峙县| 武功县| 增城市| 吕梁市| 柳江县| 新沂市| 临潭县| 临海市| 静乐县| 邓州市| 霍州市| 铅山县| 清镇市| 榆树市| 资兴市| 镇雄县| 阿拉尔市| 阳朔县| 临夏市|