真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

MyBatis的事務(wù)管理方式-創(chuàng)新互聯(lián)

這篇文章主要講解了“MyBatis的事務(wù)管理方式”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“MyBatis的事務(wù)管理方式”吧!

創(chuàng)新互聯(lián)專注于巧家企業(yè)網(wǎng)站建設(shè),響應(yīng)式網(wǎng)站建設(shè),商城網(wǎng)站建設(shè)。巧家網(wǎng)站建設(shè)公司,為巧家等地區(qū)提供建站服務(wù)。全流程按需定制制作,專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務(wù)

1. 運(yùn)行環(huán)境 Enviroment

當(dāng) MyBatis 與不同的應(yīng)用結(jié)合時(shí),需要不同的事務(wù)管理機(jī)制。與 Spring 結(jié)合時(shí),由 Spring 來管理事務(wù);單獨(dú)使用時(shí)需要自行管理事務(wù),在容器里運(yùn)行時(shí)可能由容器進(jìn)行管理。

MyBatis 用 Enviroment 來表示運(yùn)行環(huán)境,其封裝了三個(gè)屬性:

public class Configuration {
  // 一個(gè) MyBatis 的配置只對(duì)應(yīng)一個(gè)環(huán)境
  protected Environment environment;
  // 其他屬性 .....
}

public final class Environment {
  private final String id;
  private final TransactionFactory transactionFactory;
  private final DataSource dataSource;
}

2. 事務(wù)抽象

MyBatis 把事務(wù)管理抽象出 Transaction 接口,由 TransactionFactory 接口的實(shí)現(xiàn)類負(fù)責(zé)創(chuàng)建。

public interface Transaction {
  Connection getConnection() throws SQLException;
  void commit() throws SQLException;
  void rollback() throws SQLException;
  void close() throws SQLException;
  Integer getTimeout() throws SQLException;
}

public interface TransactionFactory {
  void setProperties(Properties props);
  Transaction newTransaction(Connection conn);
  Transaction newTransaction(DataSource dataSource, TransactionIsolationLevel level, boolean autoCommit);
}

Executor 的實(shí)現(xiàn)持有一個(gè) SqlSession 實(shí)現(xiàn),事務(wù)控制是委托給 SqlSession 的方法來實(shí)現(xiàn)的。

public abstract class BaseExecutor implements Executor {
  protected Transaction transaction;

  public void commit(boolean required) throws SQLException {
    if (closed) {
      throw new ExecutorException("Cannot commit, transaction is already closed");
    }
    clearLocalCache();
    flushStatements();
    if (required) {
      transaction.commit();
    }
  }

  public void rollback(boolean required) throws SQLException {
    if (!closed) {
      try {
        clearLocalCache();
        flushStatements(true);
      } finally {
        if (required) {
          transaction.rollback();
        }
      }
    }
  }

  // 省略其他方法、屬性
}

3. 與 Spring 集成的事務(wù)管理

3.1 配置 TransactionFactory

與 Spring 集成時(shí),通過 SqlSessionFactoryBean 來初始化 MyBatis 。

protected SqlSessionFactory buildSqlSessionFactory() throws IOException {
  Configuration configuration;

  XMLConfigBuilder xmlConfigBuilder = null;
  if (this.configuration != null) {
    configuration = this.configuration;
    if (configuration.getVariables() == null) {
      configuration.setVariables(this.configurationProperties);
    } else if (this.configurationProperties != null) {
      configuration.getVariables().putAll(this.configurationProperties);
    }
  } else if (this.configLocation != null) {
    xmlConfigBuilder = new XMLConfigBuilder(this.configLocation.getInputStream(), null, this.configurationProperties);
    configuration = xmlConfigBuilder.getConfiguration();
  } else {
    configuration = new Configuration();
    configuration.setVariables(this.configurationProperties);
  }

  if (this.objectFactory != null) {
    configuration.setObjectFactory(this.objectFactory);
  }

  if (this.objectWrapperFactory != null) {
    configuration.setObjectWrapperFactory(this.objectWrapperFactory);
  }

  if (this.vfs != null) {
    configuration.setVfsImpl(this.vfs);
  }

  if (hasLength(this.typeAliasesPackage)) {
    String[] typeAliasPackageArray = tokenizeToStringArray(this.typeAliasesPackage,
    ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
    for (String packageToScan : typeAliasPackageArray) {
      configuration.getTypeAliasRegistry().registerAliases(packageToScan,
      typeAliasesSuperType == null ? Object.class : typeAliasesSuperType);
    }
  }

  if (!isEmpty(this.typeAliases)) {
    for (Class typeAlias : this.typeAliases) {
      configuration.getTypeAliasRegistry().registerAlias(typeAlias);
    }
  }

  if (!isEmpty(this.plugins)) {
    for (Interceptor plugin : this.plugins) {
      configuration.addInterceptor(plugin);
    }
  }

  if (hasLength(this.typeHandlersPackage)) {
    String[] typeHandlersPackageArray = tokenizeToStringArray(this.typeHandlersPackage,
    ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
    for (String packageToScan : typeHandlersPackageArray) {
      configuration.getTypeHandlerRegistry().register(packageToScan);
    }
  }

  if (!isEmpty(this.typeHandlers)) {
    for (TypeHandler typeHandler : this.typeHandlers) {
      configuration.getTypeHandlerRegistry().register(typeHandler);
    }
  }

  if (this.databaseIdProvider != null) {//fix #64 set databaseId before parse mapper xmls
    try {
      configuration.setDatabaseId(this.databaseIdProvider.getDatabaseId(this.dataSource));
    } catch (SQLException e) {
      throw new NestedIOException("Failed getting a databaseId", e);
    }
  }

  if (this.cache != null) {
    configuration.addCache(this.cache);
  }

  if (xmlConfigBuilder != null) {
    try {
      xmlConfigBuilder.parse();
    } catch (Exception ex) {
      throw new NestedIOException("Failed to parse config resource: " + this.configLocation, ex);
    } finally {
      ErrorContext.instance().reset();
    }
  }

  // 創(chuàng)建 SpringManagedTransactionFactory
  if (this.transactionFactory == null) {
    this.transactionFactory = new SpringManagedTransactionFactory();
  }

  // 封裝成 Environment
  configuration.setEnvironment(new Environment(this.environment, this.transactionFactory, this.dataSource));

  if (!isEmpty(this.mapperLocations)) {
    for (Resource mapperLocation : this.mapperLocations) {
      if (mapperLocation == null) {
        continue;
      }

      try {
        XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(mapperLocation.getInputStream(),
        configuration, mapperLocation.toString(), configuration.getSqlFragments());
        xmlMapperBuilder.parse();
      } catch (Exception e) {
        throw new NestedIOException("Failed to parse mapping resource: '" + mapperLocation + "'", e);
      } finally {
        ErrorContext.instance().reset();
      }
    }
  } else {
  }

  return this.sqlSessionFactoryBuilder.build(configuration);
}
public class SqlSessionFactoryBuilder {
  public SqlSessionFactory build(Configuration config) {
    return new DefaultSqlSessionFactory(config);
  }
}

重點(diǎn)是在構(gòu)建 MyBatis Configuration 對(duì)象時(shí),把 transactionFactory 配置成 SpringManagedTransactionFactory,再封裝成 Environment 對(duì)象。

3.2 運(yùn)行時(shí)事務(wù)管理

Mapper 的代理對(duì)象持有的是 SqlSessionTemplate,其實(shí)現(xiàn)了 SqlSession 接口。

SqlSessionTemplate 的方法并不直接調(diào)用具體的 SqlSession 的方法,而是委托給一個(gè)動(dòng)態(tài)代理,通過代理 SqlSessionInterceptor 對(duì)方法調(diào)用進(jìn)行攔截。

SqlSessionInterceptor 負(fù)責(zé)獲取真實(shí)的與數(shù)據(jù)庫(kù)關(guān)聯(lián)的 SqlSession 實(shí)現(xiàn),并在方法執(zhí)行完后決定提交或回滾事務(wù)、關(guān)閉會(huì)話。

public class SqlSessionTemplate implements SqlSession, DisposableBean {
  private final SqlSessionFactory sqlSessionFactory;
  private final ExecutorType executorType;
  private final SqlSession sqlSessionProxy;
  private final PersistenceExceptionTranslator exceptionTranslator;

  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;

    // 因?yàn)?nbsp;SqlSession 接口聲明的方法也不少,
    // 在每個(gè)方法里添加事務(wù)相關(guān)的攔截比較麻煩,
    // 不如創(chuàng)建一個(gè)內(nèi)部的代理對(duì)象進(jìn)行統(tǒng)一處理。
    this.sqlSessionProxy = (SqlSession) newProxyInstance(
      SqlSessionFactory.class.getClassLoader(),
      new Class[] { SqlSession.class },
      new SqlSessionInterceptor());
  }

  public int update(String statement) {
    // 在代理對(duì)象上執(zhí)行方法調(diào)用
    return this.sqlSessionProxy.update(statement);
  }

  // 對(duì)方法調(diào)用進(jìn)行攔截,加入事務(wù)控制邏輯
  private class SqlSessionInterceptor implements InvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      // 獲取與數(shù)據(jù)庫(kù)關(guān)聯(lián)的會(huì)話
      SqlSession sqlSession = SqlSessionUtils.getSqlSession(
        SqlSessionTemplate.this.sqlSessionFactory,
        SqlSessionTemplate.this.executorType,
        SqlSessionTemplate.this.exceptionTranslator);
      try {
        // 執(zhí)行 SQL 操作
        Object result = method.invoke(sqlSession, args);
        if (!SqlSessionUtils.isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) {
          // 如果 sqlSession 不是 Spring 管理的,則要自行提交事務(wù)
          sqlSession.commit(true);
        }
        return result;
      } catch (Throwable t) {
        Throwable unwrapped = unwrapThrowable(t);
        if (SqlSessionTemplate.this.exceptionTranslator != null && unwrapped instanceof PersistenceException) {

          SqlSessionUtils.closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
          sqlSession = null;
          Throwable translated = SqlSessionTemplate.this.exceptionTranslator.translateExceptionIfPossible((PersistenceException) unwrapped);
          if (translated != null) {
            unwrapped = translated;
          }
        }
        throw unwrapped;
      } finally {
        if (sqlSession != null) {
          SqlSessionUtils.closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
        }
      }
    }
  }
}

SqlSessionUtils 封裝了對(duì) Spring 事務(wù)管理機(jī)制的訪問。

// SqlSessionUtils
public static SqlSession getSqlSession(SqlSessionFactory sessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) {
  // 從 Spring 的事務(wù)管理機(jī)制那里獲取當(dāng)前事務(wù)關(guān)聯(lián)的會(huì)話
  SqlSessionHolder holder = (SqlSessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);

  SqlSession session = sessionHolder(executorType, holder);
  if (session != null) {
    // 已經(jīng)有一個(gè)會(huì)話則復(fù)用
    return session;
  }

  // 創(chuàng)建新的 會(huì)話
  session = sessionFactory.openSession(executorType);

  // 注冊(cè)到 Spring 的事務(wù)管理機(jī)制里
  registerSessionHolder(sessionFactory, executorType, exceptionTranslator, session);

  return session;
}

private static void registerSessionHolder(SqlSessionFactory sessionFactory, ExecutorType executorType,
    PersistenceExceptionTranslator exceptionTranslator, SqlSession session) {
  SqlSessionHolder holder;
  if (TransactionSynchronizationManager.isSynchronizationActive()) {
    Environment environment = sessionFactory.getConfiguration().getEnvironment();

    if (environment.getTransactionFactory() instanceof SpringManagedTransactionFactory) {
      holder = new SqlSessionHolder(session, executorType, exceptionTranslator);
      TransactionSynchronizationManager.bindResource(sessionFactory, holder);

      // 重點(diǎn):注冊(cè)會(huì)話管理的回調(diào)鉤子,真正的關(guān)閉動(dòng)作是在回調(diào)里完成的。
      TransactionSynchronizationManager.registerSynchronization(new SqlSessionSynchronization(holder, sessionFactory));
      holder.setSynchronizedWithTransaction(true);

      // 維護(hù)會(huì)話的引用計(jì)數(shù)
      holder.requested();
    } else {
      if (TransactionSynchronizationManager.getResource(environment.getDataSource()) == null) {
      } else {
        throw new TransientDataAccessResourceException(
          "SqlSessionFactory must be using a SpringManagedTransactionFactory in order to use Spring transaction synchronization");
      }
    }
  } else {
  }
}

public static void closeSqlSession(SqlSession session, SqlSessionFactory sessionFactory) {
  // 從線程本地變量里獲取 Spring 管理的會(huì)話
  SqlSessionHolder holder = (SqlSessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
  if ((holder != null) && (holder.getSqlSession() == session)) {
    // Spring 管理的不直接關(guān)閉,由回調(diào)鉤子來關(guān)閉
    holder.released();
  } else {
    // 非 Spring 管理的直接關(guān)閉
    session.close();
  }
}

SqlSessionSynchronization 是 SqlSessionUtils 的內(nèi)部私有類,用于作為回調(diào)鉤子與 Spring 的事務(wù)管理機(jī)制協(xié)調(diào)工作,TransactionSynchronizationManager 在適當(dāng)?shù)臅r(shí)候回調(diào)其方法。

private static final class SqlSessionSynchronization extends TransactionSynchronizationAdapter {
  private final SqlSessionHolder holder;
  private final SqlSessionFactory sessionFactory;
  private boolean holderActive = true;

  public SqlSessionSynchronization(SqlSessionHolder holder, SqlSessionFactory sessionFactory) {
    this.holder = holder;
    this.sessionFactory = sessionFactory;
  }

  public int getOrder() {
    return DataSourceUtils.CONNECTION_SYNCHRONIZATION_ORDER - 1;
  }

  public void suspend() {
    if (this.holderActive) {
      TransactionSynchronizationManager.unbindResource(this.sessionFactory);
    }
  }

  public void resume() {
    if (this.holderActive) {
      TransactionSynchronizationManager.bindResource(this.sessionFactory, this.holder);
    }
  }

  public void beforeCommit(boolean readOnly) {
    if (TransactionSynchronizationManager.isActualTransactionActive()) {
      try {
        this.holder.getSqlSession().commit();
      } catch (PersistenceException p) {
        if (this.holder.getPersistenceExceptionTranslator() != null) {
          DataAccessException translated = this.holder
            .getPersistenceExceptionTranslator()
            .translateExceptionIfPossible(p);
          if (translated != null) {
            throw translated;
          }
        }
        throw p;
      }
    }
  }

  public void beforeCompletion() {
    if (!this.holder.isOpen()) {
      TransactionSynchronizationManager.unbindResource(sessionFactory);
      this.holderActive = false;

      // 真正關(guān)閉數(shù)據(jù)庫(kù)會(huì)話
      this.holder.getSqlSession().close();
    }
  }

  public void afterCompletion(int status) {
    if (this.holderActive) {
      TransactionSynchronizationManager.unbindResourceIfPossible(sessionFactory);
      this.holderActive = false;

      // 真正關(guān)閉數(shù)據(jù)庫(kù)會(huì)話
      this.holder.getSqlSession().close();
    }
    this.holder.reset();
  }
}

3.3 創(chuàng)建新會(huì)話

// DefaultSqlSessionFactory
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
  Transaction tx = null;
  try {
    final Environment environment = configuration.getEnvironment();

    // 獲取事務(wù)工廠實(shí)現(xiàn)
    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();
  }
}

private TransactionFactory getTransactionFactoryFromEnvironment(Environment environment) {
  if (environment == null || environment.getTransactionFactory() == null) {
    return new ManagedTransactionFactory();
  }
  return environment.getTransactionFactory();
}

4. 小結(jié)

  1. MyBatis 的核心組件 Executor 通過 Transaction 接口來進(jìn)行事務(wù)控制。

  2. 與 Spring 集成時(shí),初始化 Configuration 時(shí)會(huì)把 transactionFactory 設(shè)置為 SpringManagedTransactionFactory 的實(shí)例。

  3. 每個(gè) Mapper 代理里注入的 SqlSession 是 SqlSessionTemplate 的實(shí)例,其實(shí)現(xiàn)了 SqlSession 接口;

  4. SqlSessionTemplate 把對(duì) SqlSession 接口里聲明的方法調(diào)用委托給內(nèi)部的一個(gè)動(dòng)態(tài)代理,該代理的方法處理器為內(nèi)部類 SqlSessionInterceptor 。

  5. SqlSessionInterceptor 接收到方法調(diào)用時(shí),通過 SqlSessionUtil 訪問 Spring 的事務(wù)設(shè)施,如果有與 Spring 當(dāng)前事務(wù)關(guān)聯(lián)的 SqlSession 則復(fù)用;沒有則創(chuàng)建一個(gè)。

  6. SqlSessionInterceptor 根據(jù) Spring 當(dāng)前事務(wù)的狀態(tài)來決定是否提交或回滾事務(wù)。會(huì)話的真正關(guān)閉是通過注冊(cè)在 TransactionSynchronizationManager 上的回調(diào)鉤子實(shí)現(xiàn)的。

感謝各位的閱讀,以上就是“MyBatis的事務(wù)管理方式”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對(duì)MyBatis的事務(wù)管理方式這一問題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián)建站,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)建站www.cdcxhl.com,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。


文章題目:MyBatis的事務(wù)管理方式-創(chuàng)新互聯(lián)
路徑分享:http://weahome.cn/article/jsehj.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部