欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

注意僅有當(dāng)數(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與線程綁定,如果當(dāng)前線程未綁定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當(dāng)中的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相當(dāng)于數(shù)據(jù)庫連接池,那么SqlSession就相當(dāng)于一個數(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中快速排序優(yōu)化技巧之隨機取樣、三數(shù)取中和插入排序

    Java中快速排序優(yōu)化技巧之隨機取樣、三數(shù)取中和插入排序

    快速排序是一種常用的基于比較的排序算法,下面這篇文章主要給大家介紹了關(guān)于Java中快速排序優(yōu)化技巧之隨機取樣、三數(shù)取中和插入排序的相關(guān)資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2023-09-09
  • Java基礎(chǔ)知識之注解、元注解

    Java基礎(chǔ)知識之注解、元注解

    ava 注解,從名字上看是注釋,解釋。但功能卻不僅僅是注釋那么簡單,下面這篇文章主要給大家介紹了關(guān)于Java基礎(chǔ)知識之注解、元注解的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-01-01
  • RocketMQ中消費者的消費進度管理

    RocketMQ中消費者的消費進度管理

    這篇文章主要介紹了RocketMQ中消費者的消費進度管理,業(yè)務(wù)實現(xiàn)消費回調(diào)的時候,當(dāng)且僅當(dāng)此回調(diào)函數(shù)返回ConsumeConcurrentlyStatus.CONSUME_SUCCESS ,RocketMQ才會認為這批消息(默認是1條)是消費完成的,需要的朋友可以參考下
    2023-10-10
  • Java注解簡單使用實例解析

    Java注解簡單使用實例解析

    這篇文章主要介紹了Java注解簡單使用實例解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-06-06
  • Java Annotation注解相關(guān)原理代碼總結(jié)

    Java Annotation注解相關(guān)原理代碼總結(jié)

    這篇文章主要介紹了Java Annotation注解相關(guān)原理代碼總結(jié),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-07-07
  • 解決kafka消息堆積及分區(qū)不均勻的問題

    解決kafka消息堆積及分區(qū)不均勻的問題

    這篇文章主要介紹了解決kafka消息堆積及分區(qū)不均勻的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • Java中static靜態(tài)變量的初始化完全解析

    Java中static靜態(tài)變量的初始化完全解析

    static所聲明的變量在Java中有一個初始化的先后順序,帶著這個問題接下來我們就來進行Java中static靜態(tài)變量的初始化完全解析:
    2016-06-06
  • Spring?Cloud?Alibaba?Nacos服務(wù)治理平臺服務(wù)注冊、RestTemplate實現(xiàn)微服務(wù)之間訪問負載均衡訪問的問題

    Spring?Cloud?Alibaba?Nacos服務(wù)治理平臺服務(wù)注冊、RestTemplate實現(xiàn)微服務(wù)之間訪

    這篇文章主要介紹了Spring?Cloud?Alibaba:Nacos服務(wù)治理平臺,服務(wù)注冊、RestTemplate實現(xiàn)微服務(wù)之間訪問,負載均衡訪問,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-06-06
  • Java?C++刷題leetcode1106解析布爾表達式

    Java?C++刷題leetcode1106解析布爾表達式

    這篇文章主要為大家介紹了Java?C++刷題leetcode1106解析布爾表達式示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-01-01
  • Java 數(shù)據(jù)結(jié)構(gòu)算法Collection接口迭代器示例詳解

    Java 數(shù)據(jù)結(jié)構(gòu)算法Collection接口迭代器示例詳解

    這篇文章主要為大家介紹了Java 數(shù)據(jù)結(jié)構(gòu)算法Collection接口迭代器示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-09-09

最新評論