美文网首页Mybatis源码之路
MyBatis Connection 对象存在在哪里?

MyBatis Connection 对象存在在哪里?

作者: 93张先生 | 来源:发表于2020-09-17 10:15 被阅读0次

平时查询数据库

public static void main(String[] args) {
        //声明Connection对象
        Connection con;
        //驱动程序名
        String driver = "com.mysql.jdbc.Driver";
        //URL指向要访问的数据库名studb
        String url = "jdbc:mysql://localhost:3306/studb";
        //MySQL配置时的用户名
        String user = "root";
        //MySQL配置时的密码
        String password = "12345";
        
        //遍历查询结果集
        try {
            
            //加载驱动程序
            Class.forName(driver);
            //1.getConnection()方法,连接MySQL数据库!!
            con = DriverManager.getConnection(url,user,password);
            
            if(!con.isClosed())
                System.out.println("Succeeded connecting to the Database!");
            //2.创建statement类对象,用来执行SQL语句!!
            Statement statement = con.createStatement();
            //要执行的SQL语句
            String sql = "select * from t_stu";
            
            //3.ResultSet类,用来存放获取的结果集!!
            ResultSet rs = statement.executeQuery(sql);
            System.out.println("-----------------");
            System.out.println("执行结果如下所示:"); 
            System.out.println("-----------------"); 
            System.out.println("姓名" + "\t" + "地址"); 
            System.out.println("-----------------");  
            
            String address = null;
            
            String name = null;
            
            while(rs.next()){
                //获取sname这列数据
                name = rs.getString("sname");
                //获取address这列数据
                address = rs.getString("address");
                //输出结果
                System.out.println(name + "\t" + address);
            }
            rs.close();
            con.close();
        }catch(ClassNotFoundException e) {
            //数据库驱动类异常处理
            System.out.println("Sorry,can`t find the Driver!"); 
            e.printStackTrace();
        }catch(SQLException e) {
            //数据库连接失败异常处理
            e.printStackTrace(); 
        }catch (Exception e) {
             e.printStackTrace();
        }finally{
            System.out.println("数据库数据成功获取!!");
        }

    }

MyBatis 查询流程

image.png

疑问

从 MyBatis 查询流程中看不到 Connection 对象的身影,那 Connection 对象出现在哪里了呢?怎样初始化的呢?

答:实际 Connection 对象是在 Transaction 中,由 Connection 和 数据库事务 组成了 Transaction 对象。Transaction 对象是在 BaseExecutor 中, Transaction 在 Executor 中提供了事务的功能。

DataSource 初始化是在 XMLConfigBuilder 解析 mybatis-config.xml 配置的 dataSource 节点中。同时也创建了 TransactionFactory 对象。并把 DataSource 和 TransactionFactory 封装进了 Environment,然后写入了 Configuration 对象。

  /**
   * <environments default="development">
   *     <environment id="development">
   *       <transactionManager type="JDBC">
   *         <property name="" value="" />
   *       </transactionManager>
   *       <dataSource type="UNPOOLED">
   *         <property name="driver" value="org.hsqldb.jdbcDriver" />
   *         <property name="url" value="jdbc:hsqldb:mem:localtime" />
   *         <property name="username" value="sa" />
   *       </dataSource>
   *     </environment>
   *   </environments>
   *
   * @param context
   * @throws Exception
   */
  private void environmentsElement(XNode context) throws Exception {
    if (context != null) {
      //未指定 XMLConfigBuilder environment 字段,则使用 default 性指定的 <environment>
      if (environment == null) {
        environment = context.getStringAttribute("default");
      }
      for (XNode child : context.getChildren()) {
        String id = child.getStringAttribute("id");
        if (isSpecifiedEnvironment(id)) {
          TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager")); // 创建 TransactionFactory
          DataSourceFactory dsFactory = dataSourceElement(child.evalNode("dataSource")); // 创建 DataSourceFactory
          DataSource dataSource = dsFactory.getDataSource();        // 创建 DataSource
          Environment.Builder environmentBuilder = new Environment.Builder(id)
              .transactionFactory(txFactory)
              .dataSource(dataSource);
          configuration.setEnvironment(environmentBuilder.build()); // 创建 Environment,并反写 configuration 对象
        }
      }
    }
  }
  /**
   * 根据 配置文件中的节点,创建 DataSourceFactory 对象
   * @param context
   * @return
   * @throws Exception
   */
  private DataSourceFactory dataSourceElement(XNode context) throws Exception {
    if (context != null) {
      String type = context.getStringAttribute("type");
      Properties props = context.getChildrenAsProperties();
      DataSourceFactory factory = (DataSourceFactory) resolveClass(type).getDeclaredConstructor().newInstance();
      factory.setProperties(props);
      return factory;
    }
    throw new BuilderException("Environment declaration requires a DataSourceFactory.");
  }

Transaction 对象初始化

在 DefaultSqlSessionFactory 中的 openSessionFromDataSource(),方法中获取项目初始化的 TransactionFactory,然后由 TransactionFactory 创建 Transaction 对象,然后再由 Transaction 对象创建 Executor 对象,因为 Transaction 对象中包含了 Connection 对象,所以 Executor 中也有了 Connection 对象。

  private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
    Transaction tx = null;
    try {
      // 获取 mybatis-config.xml 配置文件中配置的 Environment 对象
      final Environment environment = configuration.getEnvironment();
      // 获取 TransactionFactory
      final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
      // 创建 Transaction 对象
      tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
      // 创建 Executor 对象
      final Executor executor = configuration.newExecutor(tx, execType);
      // 创建 DefaultSqlSession 对象
      return new DefaultSqlSession(configuration, executor, autoCommit);
    } catch (Exception e) {
      // 关闭 Transaction
      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 Connection 对象存在在哪里?

    本文链接:https://www.haomeiwen.com/subject/gqyqyktx.html