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的默认实现类)

 

posted @ 2018-08-14 20:49  Lucky帅小武  阅读(2577)  评论(0编辑  收藏  举报