美文网首页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