亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Mybatis SqlSessionFactory與SqlSession詳細講解

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

SqlssionFactory

1.SqlSessionFactory是MyBatis的關鍵對象,它是個單個數據庫映射關系經過編譯后的內存鏡像。

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

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

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

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

SqlSessionFactory接口源碼如下所示

package org.apache.ibatis.session; 
import java.sql.Connection; 
public interface SqlSessionFactory { 
  SqlSession openSession();//這個方法最經常用,用來創(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默認實現的MybatisAutoConfiguration來看看

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

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

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

SqlSessionTemplate

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

創(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());
  }

內部的sqlSessionProxy是對sqlSession做的代理

處理類是SqlSessionInterceptor

SqlSessionTemplate繼承自SqlSession,實現了sqlSession的所有操作

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

可以看出來,SqlSessionTemplate就是對SqlSession套了個殼子,具體實現還是有代理的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實現)。

 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一定只能被一個線程使用。

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

SqlSession

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

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

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

4.每個線程都應該有它自己的SqlSession實例。

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

6.使用完SqlSeesion之后關閉Session很重要,應該確保使用finally塊來關閉它。

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)建一個事務,創(chuàng)建一個Executor,構造DefaultSqlSession

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

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

調用 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相當于數據庫連接池,那么SqlSession就相當于一個數據庫連接(Connection對象),

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

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

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

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

相關文章

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

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

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

    Java基礎知識之注解、元注解

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

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

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

    Java注解簡單使用實例解析

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

    Java Annotation注解相關原理代碼總結

    這篇文章主要介紹了Java Annotation注解相關原理代碼總結,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    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服務治理平臺服務注冊、RestTemplate實現微服務之間訪問負載均衡訪問的問題

    Spring?Cloud?Alibaba?Nacos服務治理平臺服務注冊、RestTemplate實現微服務之間訪

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

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

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

    Java 數據結構算法Collection接口迭代器示例詳解

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

最新評論