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 }
由源碼可知該類共有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的默認實現類)
