SqlSession创建Mybatis源码解析

我们先回顾一下,在前面的示例中是怎么获取SqlSession,然后再分析源码。

try { //资源文件的名称String resource = "configuration.xml"; //使用Resources工具类加载资源Reader reader = Resources.getResourceAsReader(resource); //使用SqlSessionFactoryBuilder创建一个SqlSessionFactorySqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader); //使用SqlSessionFactory打开一个SqlSession实例,通过SqlSession来进行数据库操作SqlSession session = factory.openSession();} catch (IOException e) { e.printStackTrace();}

从上面的代码知道,我们分析的入口是SqlSessionFactoryBuilder类,下面我们看看SqlSessionFactoryBuilder这个类。

SqlSessionFactoryBuilder

SqlSessionFactoryBuilder负责创建SqlSessionFactory对象,在创建SqlSessionFactory对象的同时,也通过Reader构建出了Configuration对象。SqlSessionFactory提供了一个带Configuration参数的构造方法。这样返回的factory实例就拥有了所以的配置资源信息。SqlSessionFactoryBuilder提供了build()方法,该方法用于获取配置资源文件,该方法有很多重载版本,下面我们看看这个方法。

下面是build()的重载方法:

public SqlSessionFactory build(Reader reader)public SqlSessionFactory build(Reader reader, String environment)public SqlSessionFactory build(Reader reader, Properties properties)public SqlSessionFactory build(Reader reader, String environment, Properties properties)public SqlSessionFactory build(InputStream inputStream)public SqlSessionFactory build(InputStream inputStream, String environment)public SqlSessionFactory build(InputStream inputStream, Properties properties)public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties)

我们选一个进行分析:

public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) catch (Exception e) { throw ExceptionFactory.wrapException("Error building SqlSession.", e);} finally catch (IOException e) { // Intentionally ignore. Prefer previous error.}}}public SqlSessionFactory build(Configuration config)

使用XMLConfigBuilder解析XML文件,获取到表示资源配置的类Configuration,然后创建默认的SqlSessionFactoryBuilder实现类DefaultSqlSessionFactory。

SqlSessionFactory

SqlSessionFactory实例在创建时就拥有了所有的配置信息,SqlSessionFactory提供了openSession()方法来创建SqlSession对象,而我们在程序中可以直接调用SqlSession的方法来操作数据库。openSession()方法提供了很多重载的版本,但最终都是调用openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit)这个方法,在这个方法中提供了3个参数。

SqlSessionFactory对象负责打开一个SqlSession实例,SqlSession是Mybatis进行数据库操作的接口。下面看看SqlSessionFactory中是怎样定义的。

public interface SqlSessionFactory

根据接口定义就可以看出,SqlSessionFactory根据执行器类型、是否提交、事务等级、数据库连接等来创建不同的SqlSession实例。以及,SqlSessionFactory需要持有一个Configuration对象,需要知道XML资源是怎样配置的。

看DefaultSqlSessionFactor源码可以知道,这些重载方法最终都是调用了下面的方法:

private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit)

先看看openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit)。

第一个参数execType表示的是执行器的类型,Mybatis提供了3中执行器;第二个参数表示的是事务等级,Mybatis提供了5种事务等级;第三个参数表示事务事务是否自动提交。下面是ExecutorType枚举和TransactionIsolationLevel枚举的定义。

public enum ExecutorType public enum TransactionIsolationLevel

下面我们在看看DefaultSqlSessionFactor#openSessionFromDataSource()这个方法的源代码。

private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) catch (Exception e) { //关闭事务closeTransaction(tx); // may have fetched a connection so lets call close()throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);} finally }

创建SqlSession主要有以下几个步骤:

获取配置环境Environment对象 Configuration对象创建时,就已经创建好了Environment 对象,所以直接调用Configuration#getEnvironment()可以获取

创建事务Transaction对象 这里使用了工厂模式,提供了2种事务工厂:JdbcTransactionFactory和ManagedTransactionFactory, JdbcTransactionFactory使用的是Jdbc的事务,ManagedTransactionFactory使用的是管理型事务,如Spring容器管理事务。

创建执行器Executor对象 Executor对象的创建也是在Configuration中的,调用newExecutor()方法,根据ExecutorType类型来使用不同的实现类,Executor接口提供了拦截器链的处理,拦截器负责拦截Interceptor接口。

创建SqlSession对象 SqlSession接口提供了一个DefaultSqlSession的实现类,构造方法DefaultSqlSession(Configuration configuration, Executor executor), 这样在创建时把Configuration和Executor都传递到了SqlSession中。

Mybatis获取事务

事务Transaction是通过事务工厂TransactionFactory获取的,在上面的源码中也就是通过TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment)获取,然后调用TransactionFactory#newTransaction(dataSource, level, autoCommit)方法获取到事务对象。先看看getTransactionFactoryFromEnvironment(environment)方法,看看如何获取到事务工厂的。

private TransactionFactory getTransactionFactoryFromEnvironment(Environment environment) return environment.getTransactionFactory();}

获取方式很简单,如果在Environment中配置了事务工厂,则使用配置的事务工厂,如果没有配置,则使用ManagedTransactionFactory这个实现。

在Mybatis中提供了TransactionFactory和Transaction这2个接口来处理数据库事务,这里使用的是抽象工厂模式,提供了3类工厂类。TransactionFactory负责创建Transaction对象,具体的实现类由不同的事务工厂来创建。在Mybatis中提供了3种事务JdbcTransaction、ManagedTransaction和SpringManagedTransaction。

Executor执行器创建

创建Executor是通过调用Configuration#newExecutor(Transaction transaction, ExecutorType executorType, boolean autoCommit)方法,下面逐行分析下这个方法。

public Executor newExecutor(Transaction transaction, ExecutorType executorType, boolean autoCommit) {//获取配置的执行器类型,如果没有配置,则使用默认的simple类型executorType = executorType == null ? defaultExecutorType : executorType;executorType = executorType == null ? ExecutorType.SIMPLE : executorType;Executor executor;//根据执行器类型,创建具体的执行器(3中基本执行器)if (ExecutorType.BATCH == executorType) else if (ExecutorType.REUSE == executorType) else //根据配置,判断是否创建缓存执行器if (cacheEnabled) //执行器可以被拦截代理,这里使用了JDK动态代理创建一个被代理过的执行器,Mybatis提供的拦截器在后面会分篇介绍executor = (Executor) interceptorChain.pluginAll(executor);return executor;}

执行器类型executorType和缓存开关cacheEnabled是通过

配置的,配置如下:

SqlSession创建

在获得到了Executor实例之后,直接通过DefaultSqlSession的构造方法DefaultSqlSession(Configuration configuration, Executor executor)就可以创建SqlSession对象了。

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180227A1FRFB00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券