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

 

转载于:https://www.cnblogs.com/jackion5/p/9477798.html

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MyBatis是一款开源的持久层框架,它支持自定义SQL、存储过程和高级映射。本文将深度解析MyBatis源码,包括其核心组件和实现原理。 1. MyBatis的核心组件 MyBatis的核心组件包括: - SqlSessionFactoryBuilder:用于创建SqlSessionFactory,它会读取配置文件并创建相应的对象。 - SqlSessionFactory:用于创建SqlSession,它是线程安全的,因此可以被共享。 - SqlSession:用于执行SQL语句,它是非线程安全的,因此每个线程都需要创建自己的SqlSession。 - Executor:用于执行SQL语句。 - StatementHandler:用于处理SQL语句的处理器。 - ParameterHandler:用于处理参数的处理器。 - ResultSetHandler:用于处理结果集的处理器。 - MappedStatement:映射配置信息,包括SQL语句、参数类型、返回值类型等。 - Configuration:MyBatis的配置信息,包括数据源、类型转换器、映射配置等。 2. MyBatis的实现原理 MyBatis的实现原理主要包括以下几个方面: 2.1 映射配置 MyBatis使用XML或注解的方式进行映射配置,其配置信息包括: - 映射文件的命名空间。 - 映射文件中定义的SQL语句,包括select、insert、update、delete等。 - SQL语句的参数类型和返回值类型。 - SQL语句的参数映射关系,包括#{paramName}形式的占位符和${paramName}形式的变量。 - SQL语句的结果映射关系,包括<resultMap>标签和<result>标签。 2.2 解析配置文件 MyBatis会通过SqlSessionFactoryBuilder读取配置文件,并将其解析成一个Configuration对象。解析过程中会进行数据源的配置、类型转换器的配置、映射配置的加载等。 2.3 创建SqlSessionFactory MyBatis解析配置文件之后,会根据配置信息创建SqlSessionFactory对象。SqlSessionFactory是线程安全的,因此可以被共享。它主要负责创建SqlSession对象。 2.4 创建SqlSession 每个SqlSession都会绑定一个Connection对象,因此它是非线程安全的。MyBatis会为每个线程创建自己的SqlSession对象。SqlSession主要负责执行SQL语句。 2.5 执行SQL语句 MyBatis在执行SQL语句时,会先根据SQL语句的ID从MappedStatement中获取相应的映射信息,然后使用Executor执行SQL语句。在执行SQL语句时,会使用StatementHandler处理SQL语句,ParameterHandler处理参数,ResultSetHandler处理结果集。 3. 总结 本文深度解析MyBatis源码,包括其核心组件和实现原理。MyBatis是一个功能强大的持久层框架,可以帮助我们简化数据库操作。同时,MyBatis源码也值得我们深入学习和研究。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值