zoukankan      html  css  js  c++  java
  • mybatis源码解析2---SqlSessionFactoryBuilder、SqlSessionFactory解析

    1.先看一个mybatis最简单的Demo

            String resource = "mybatis-config.xml";
            //1.流形式读取mybatis配置文件
            InputStream stream = Resources.getResourceAsStream(resource); 
            //2.通过配置文件创建SqlSessionFactory
            SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(stream);
            //3.通过SqlSessionFactory创建sqlSession
            SqlSession session = sessionFactory.openSession();
            //4.通过SqlSession执行Sql语句获取结果
            List<User> userList = session.selectList("selectAll");
            System.out.println(userList.size());

    1.通过InputStream获取mybatis的配置文件

    2.通过SqlSessionFactoryBuilder创建SqlSessionFactory

    3.通过SqlSessionFactory创建一个SqlSession

    4.通过SqlSession执行Sql语句并获取结果

    那么接下来先来了解下SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession都是什么,是怎么工作的?

    一、SqlSessionFactoryBuilder解析

    由类名可知SqlSessionFactoryBuilder是SqlSessionFactory的构造类,而SqlSessionFactory又是SqlSession的工厂接口,SqlSession从字面意思可知是sql会话接口;

    所以SqlSessionFactoryBuilder可定义为Sql会话工厂构造类,顾名思义此类的作用就是创建SqlSessionFactory用的

    话不多说,代码写贴为敬

     1 package org.apache.ibatis.session;
     2 
     3 import java.io.IOException;
     4 import java.io.InputStream;
     5 import java.io.Reader;
     6 import java.util.Properties;
     7 import org.apache.ibatis.builder.xml.XMLConfigBuilder;
     8 import org.apache.ibatis.exceptions.ExceptionFactory;
     9 import org.apache.ibatis.executor.ErrorContext;
    10 import org.apache.ibatis.session.defaults.DefaultSqlSessionFactory;
    11 
    12 public class SqlSessionFactoryBuilder {
    13 
    14 //方法1
    15   public SqlSessionFactory build(Reader reader) {
    16     return build(reader, null, null);
    17   }
    18 
    19 //方法2
    20   public SqlSessionFactory build(Reader reader, String environment) {
    21     return build(reader, environment, null);
    22   }
    23 
    24 //方法3
    25   public SqlSessionFactory build(Reader reader, Properties properties) {
    26     return build(reader, null, properties);
    27   }
    28 
    29 //方法4
    30   public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
    31     try {
    32       XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
    33       return build(parser.parse());
    34     } catch (Exception e) {
    35       throw ExceptionFactory.wrapException("Error building SqlSession.", e);
    36     } finally {
    37       ErrorContext.instance().reset();
    38       try {
    39         reader.close();
    40       } catch (IOException e) {
    41         // Intentionally ignore. Prefer previous error.
    42       }
    43     }
    44   }
    45 
    46 //方法5
    47   public SqlSessionFactory build(InputStream inputStream) {
    48     return build(inputStream, null, null);
    49   }
    50 
    51 //方法6
    52   public SqlSessionFactory build(InputStream inputStream, String environment) {
    53     return build(inputStream, environment, null);
    54   }
    55 
    56 //方法7
    57   public SqlSessionFactory build(InputStream inputStream, Properties properties) {
    58     return build(inputStream, null, properties);
    59   }
    60 
    61 //方法8
    62   public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
    63     try {
    64       XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
    65       return build(parser.parse());
    66     } catch (Exception e) {
    67       throw ExceptionFactory.wrapException("Error building SqlSession.", e);
    68     } finally {
    69       ErrorContext.instance().reset();
    70       try {
    71         inputStream.close();
    72       } catch (IOException e) {
    73         // Intentionally ignore. Prefer previous error.
    74       }
    75     }
    76   }
    77     
    78 //方法9
    79   public SqlSessionFactory build(Configuration config) {
    80     return new DefaultSqlSessionFactory(config);
    81   }
    View Code

    由源码可知该类共有9个public方法,方法1、2、3最终都是调用了方法4;而方法5、6、7最终都是调用了方法8;而方法4和方法8都是根据传参创建了一个XMLConfiguration对象;

    然后根据XMLConfiguration对象的parse方法创建了一个Configuration对象,然后都调用了方法9,所以该类的所有方法最终都是调用了方法9。而方法9是根据传入的Configuration参数新建了一个DefaultSqlSessionFactory对象返回;

    很显然DefaultSqlSessionFactory是SqlSessionFactory接口的默认实现类(SqlSessionFactory还有一个SqlSessionManager实现类,后续继续了解)

    总结:SqlSessionFactoryBuilder根据mybatis的配置文件流创建Configuration对象,然后新建一个SqlSessionFactory的默认实现类DefaultSqlSessionFactory的对象

    二、SqlSessionFactory解析

     1 package org.apache.ibatis.session;
     2 
     3 import java.sql.Connection;
     4 
     5 /**
     6  * Creates an {@link SqlSession} out of a connection or a DataSource
     7  * 
     8  * @author Clinton Begin
     9  */
    10 public interface SqlSessionFactory {
    11 
    12   SqlSession openSession();
    13 
    14   SqlSession openSession(boolean autoCommit);
    15   SqlSession openSession(Connection connection);
    16   SqlSession openSession(TransactionIsolationLevel level);
    17 
    18   SqlSession openSession(ExecutorType execType);
    19   SqlSession openSession(ExecutorType execType, boolean autoCommit);
    20   SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level);
    21   SqlSession openSession(ExecutorType execType, Connection connection);
    22 
    23   Configuration getConfiguration();
    24 
    25 }

    SqlSessionFactory接口定义了8个创建SqlSession的接口,和一个获取Configuration,该接口的主要作用也就是创建SqlSession

    可以看出这里面涉及到了几个参数:

    autoCommit:数据库是否自动提交

    Connection:数据库连接

    TransactionIsolationLevel:数据库隔离级别

    ExecutorType:执行器类型

    这几个参数具体含义暂不讨论,后续继续了解,那么现在继续了解下SqlSessionFactory的默认实现类DefaultSqlSessionFactory

    三、DefaultSqlSessionFactory解析

    先贴下源码如下:

      1 package org.apache.ibatis.session.defaults;
      2 
      3 import java.sql.Connection;
      4 import java.sql.SQLException;
      5 
      6 import org.apache.ibatis.exceptions.ExceptionFactory;
      7 import org.apache.ibatis.executor.ErrorContext;
      8 import org.apache.ibatis.executor.Executor;
      9 import org.apache.ibatis.mapping.Environment;
     10 import org.apache.ibatis.session.Configuration;
     11 import org.apache.ibatis.session.ExecutorType;
     12 import org.apache.ibatis.session.SqlSession;
     13 import org.apache.ibatis.session.SqlSessionFactory;
     14 import org.apache.ibatis.session.TransactionIsolationLevel;
     15 import org.apache.ibatis.transaction.Transaction;
     16 import org.apache.ibatis.transaction.TransactionFactory;
     17 import org.apache.ibatis.transaction.managed.ManagedTransactionFactory;
     18 
     19 /**
     20  * @author Clinton Begin
     21  */
     22 public class DefaultSqlSessionFactory implements SqlSessionFactory {
     23 
     24   private final Configuration configuration;
     25 
     26   public DefaultSqlSessionFactory(Configuration configuration) {
     27     this.configuration = configuration;
     28   }
     29 
     30   @Override
     31   public SqlSession openSession() {
     32     return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
     33   }
     34 
     35   @Override
     36   public SqlSession openSession(boolean autoCommit) {
     37     return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, autoCommit);
     38   }
     39 
     40   @Override
     41   public SqlSession openSession(ExecutorType execType) {
     42     return openSessionFromDataSource(execType, null, false);
     43   }
     44 
     45   @Override
     46   public SqlSession openSession(TransactionIsolationLevel level) {
     47     return openSessionFromDataSource(configuration.getDefaultExecutorType(), level, false);
     48   }
     49 
     50   @Override
     51   public SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level) {
     52     return openSessionFromDataSource(execType, level, false);
     53   }
     54 
     55   @Override
     56   public SqlSession openSession(ExecutorType execType, boolean autoCommit) {
     57     return openSessionFromDataSource(execType, null, autoCommit);
     58   }
     59 
     60   @Override
     61   public SqlSession openSession(Connection connection) {
     62     return openSessionFromConnection(configuration.getDefaultExecutorType(), connection);
     63   }
     64 
     65   @Override
     66   public SqlSession openSession(ExecutorType execType, Connection connection) {
     67     return openSessionFromConnection(execType, connection);
     68   }
     69 
     70   @Override
     71   public Configuration getConfiguration() {
     72     return configuration;
     73   }
     74 
     75   private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
     76     Transaction tx = null;
     77     try {
     78       final Environment environment = configuration.getEnvironment();
     79       final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
     80       tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
     81       final Executor executor = configuration.newExecutor(tx, execType);
     82       return new DefaultSqlSession(configuration, executor, autoCommit);
     83     } catch (Exception e) {
     84       closeTransaction(tx); // may have fetched a connection so lets call close()
     85       throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
     86     } finally {
     87       ErrorContext.instance().reset();
     88     }
     89   }
     90 
     91   private SqlSession openSessionFromConnection(ExecutorType execType, Connection connection) {
     92     try {
     93       boolean autoCommit;
     94       try {
     95         autoCommit = connection.getAutoCommit();
     96       } catch (SQLException e) {
     97         // Failover to true, as most poor drivers
     98         // or databases won't support transactions
     99         autoCommit = true;
    100       }      
    101       final Environment environment = configuration.getEnvironment();
    102       final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
    103       final Transaction tx = transactionFactory.newTransaction(connection);
    104       final Executor executor = configuration.newExecutor(tx, execType);
    105       return new DefaultSqlSession(configuration, executor, autoCommit);
    106     } catch (Exception e) {
    107       throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
    108     } finally {
    109       ErrorContext.instance().reset();
    110     }
    111   }
    112 
    113   private TransactionFactory getTransactionFactoryFromEnvironment(Environment environment) {
    114     if (environment == null || environment.getTransactionFactory() == null) {
    115       return new ManagedTransactionFactory();
    116     }
    117     return environment.getTransactionFactory();
    118   }
    119 
    120   private void closeTransaction(Transaction tx) {
    121     if (tx != null) {
    122       try {
    123         tx.close();
    124       } catch (SQLException ignore) {
    125         // Intentionally ignore. Prefer previous error.
    126       }
    127     }
    128   }
    129 
    130 }

    DefaultSqlSessionFactory除了实现了SqlSessionFactory的9个接口,还有一个构造方法,也就是SqlSessionFactoryBuilder中调用的那个,然后还有4个私有方法;

    可以看出实现的8个创建SqlSession对象的接口最终都是调用了openSessionFromDataSource()或是openSessionFromConnection()两个方法

    依openSessionFromDataSource为例,源码如下:

     1 private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
     2     Transaction tx = null;
     3     try {
     4       final Environment environment = configuration.getEnvironment();//根据Configuration获取环境参数对象
     5       final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);//根据环境参数对象获取事务工厂对象
     6       tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);//根据事务工厂创建新的事务对象
     7       final Executor executor = configuration.newExecutor(tx, execType);//根据Configuration获取执行器对象
     8       return new DefaultSqlSession(configuration, executor, autoCommit);//根据3个参数创建DefaultSqlSession对象
     9     } catch (Exception e) {
    10       closeTransaction(tx); // may have fetched a connection so lets call close()
    11       throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
    12     } finally {
    13       ErrorContext.instance().reset();
    14     }
    15   }

    该方法共有三个参数

    ExecutorType:执行器类型

    TransactionIsolationLevel:事务隔离级别

    autoCommit:自动提交标识

    由源码可知,最终是创建了一个DefaultSqlSession对象,很明显是SqlSession接口的默认实现类;

    openSessionFromConnection方法和openSessionFromDataSource的区别就是参数不同,效果是一样的,最终也是返回一个DefaultSqlSession对象

    而具体的Sql的执行都是通过DefaultSqlSession对象去执行的。具体怎么执行的后续再了解;

    总结:

    1.先获取mybatis的配置文件,解析成流对象(字符流和字节流都可以)Reader和InputStream都可以

    2.通过SqlSessionFactoryBuilder根据mybatis的配置文件流创建一个Configuration对象

    3.SqlSessionFactoryBuilder根据Configuration对象创建一个DefaultSqlSessionFactory(SqlSessionFactory的默认实现类)

    4.DefaulatSqlSessionFacotry根据传入的参数,创建一个DefaultSqlSession对象(SqlSession的默认实现类)

  • 相关阅读:
    LeetCode 485. Max Consecutive Ones
    LeetCode 367. Valid Perfect Square
    LeetCode 375. Guess Number Higher or Lower II
    LeetCode 374. Guess Number Higher or Lower
    LeetCode Word Pattern II
    LeetCode Arranging Coins
    LeetCode 422. Valid Word Square
    Session 共享
    java NIO
    非阻塞IO
  • 原文地址:https://www.cnblogs.com/jackion5/p/9477798.html
Copyright © 2011-2022 走看看