zoukankan      html  css  js  c++  java
  • MyBatis整合Spring怎么使用connnection

      今天下午突然脑袋灵光一闪,就想到了mybatis在整合了spring后,在web环境下多线程的时候是怎么使用connnection的呢?

      于是我翻出了源码

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

      我们知道,mybatis本身调用getMapper方法会对mapper进行动态代理

    <mapper namespace="com.suning.rdrs.admin.dao.RdrsAdminMapper">

      我们都会在项目中写一个接口  com.suning.rdrs.admin.dao.RdrsAdminMapper,该接口就会被动态代理。

      spring在整合mybatis的时候其实就是把动态代理的mapper都封装成了bean,我们才能在service的实现类里@Autowired

      sqlsession.getMapper的逻辑不是本次要讨论的重点,它本身的逻辑也不复杂

      本文的重点是看看如何得到connectioin

      Transaction tx = null;
        try {
          final Environment environment = configuration.getEnvironment();
          final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);//实际是SpringManagedTransactionFactory
          tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);//SpringManagedTransaction

     这样executor里面就有了 SpringManagedTransaction

    protected BaseExecutor(Configuration configuration, Transaction transaction) {
        this.transaction = transaction;
        this.deferredLoads = new ConcurrentLinkedQueue<DeferredLoad>();
        this.localCache = new PerpetualCache("LocalCache");
        this.localOutputParameterCache = new PerpetualCache("LocalOutputParameterCache");
        this.closed = false;
        this.configuration = configuration;
        this.wrapper = this;
      }

      我们以SimpleExecutor的一个方法为例

    @Override
      public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
        Statement stmt = null;
        try {
          Configuration configuration = ms.getConfiguration();
          StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);
          stmt = prepareStatement(handler, ms.getStatementLog());
          return handler.update(stmt);
        } finally {
          closeStatement(stmt);
        }
      }
    private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
        Statement stmt;
        Connection connection = getConnection(statementLog);
        stmt = handler.prepare(connection);
        handler.parameterize(stmt);
        return stmt;
      }
    protected Connection getConnection(Log statementLog) throws SQLException {
        Connection connection = transaction.getConnection();
        if (statementLog.isDebugEnabled()) {
          return ConnectionLogger.newInstance(connection, statementLog, queryStack);
        } else {
          return connection;
        }
      }

    下面就是spring里面的操作了

    private void openConnection() throws SQLException {
        this.connection = DataSourceUtils.getConnection(this.dataSource);
        this.autoCommit = this.connection.getAutoCommit();
    public static Connection doGetConnection(DataSource dataSource) throws SQLException {
            Assert.notNull(dataSource, "No DataSource specified");
    
            ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);

    不陌生吧,分析spring事务的时候都建过的,就是ThreadLocal的实际应用

      总结

      在spring初始化的时候,就已经初始化了每一个mapper的代理类,并把这些代理类做成了bean。

      SqlSession在一开始就确定了,executor,同时executor也确定了  SpringManagedTransaction,但是这些都不用担心。

      每次executor在执行一个方法的时候,都会执行一次 prepareStatement,在 prepareStatement里进行connection的获取,这里就能够看出来了每个connection都和线程进行绑定的。

      

  • 相关阅读:
    Environment variable ORACLE_UNQNAME not defined. Please set ORACLE_UNQNAME to database unique name. 的解决方法
    无法打开物理文件xxx.mdf 操作系统错误 5:“5(拒绝访问。)” (Microsoft SQL Server,错误: 5120) 的解决方法
    IIS7.5 处理程序“PageHandlerFactory-Integrated”在其模块列表中有一个错误模块“ManagedPipelineHandler” 错误的解决方法
    datetime
    9.29中文词频统计
    9.26文件方式实现完整的英文词频统计实例
    9.22
    英文词频统计预备,组合数据类型练习
    9.19凯撒密码、GDP格式化输出、99乘法表
    9.15字符串基本操作
  • 原文地址:https://www.cnblogs.com/juniorMa/p/13921627.html
Copyright © 2011-2022 走看看