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的默認實現類)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM