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 }
由源码可知该类共有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的默认实现类)