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都和线程进行绑定的。

      

  • 相关阅读:
    博客园
    未释放的已删除文件
    ssh连接缓慢
    剑指 Offer 38. 字符串的排列
    剑指 Offer 37. 序列化二叉树
    剑指 Offer 50. 第一个只出现一次的字符
    剑指 Offer 36. 二叉搜索树与双向链表
    剑指 Offer 35. 复杂链表的复制
    剑指 Offer 34. 二叉树中和为某一值的路径
    剑指 Offer 33. 二叉搜索树的后序遍历序列
  • 原文地址:https://www.cnblogs.com/juniorMa/p/13921627.html
Copyright © 2011-2022 走看看