对SqlSessionFactory的浅显理解

在学习Mybatis的时,看到了SqlSessionFactory,然后就结合源码和网上大佬的总结大致了解了一下流程。

String resource = "/mybatis-config.xml";

InputStream inputStream = Resources.class.getResourceAsStream(resource);

SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

在刚开始学习Mybatis的时候,想必大家对上面这个几行东西都很熟悉,所以就来探究学习一下其内部流程。

SqlSessionFactory源码

public interface SqlSessionFactory {

    SqlSession openSession();

    SqlSession openSession(boolean var1);

     SqlSession openSession(Connection var1);

    SqlSession openSession(TransactionIsolationLevel var1);

    SqlSession openSession(ExecutorType var1);

    SqlSession openSession(ExecutorType var1, boolean var2);

    SqlSession openSession(ExecutorType var1, TransactionIsolationLevel var2);

    SqlSession openSession(ExecutorType var1, Connection var2);

    Configuration getConfiguration();

}

SqlSessionFactoryBuilder()

先看一下几种不同的build方法

1、

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

    SqlSessionFactory var5;

    try {

        XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);

        var5 = this.build(parser.parse());

    } catch (Exception var14) {

        throw ExceptionFactory.wrapException("Error building SqlSession.", var14);

    } finally {

        ErrorContext.instance().reset();

        try {

            reader.close();

        } catch (IOException var13) {

        }

    }

    return var5;

}

 

2、

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

    SqlSessionFactory var5;

    try {

        XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);

        var5 = this.build(parser.parse());

    } catch (Exception var14) {

        throw ExceptionFactory.wrapException("Error building SqlSession.", var14);

    } finally {

        ErrorContext.instance().reset();

        try {

            inputStream.close();

        } catch (IOException var13) {

        }

    }

    return var5;

}

 

3、

public SqlSessionFactory build(Configuration config) {

    return new DefaultSqlSessionFactory(config);

}

 

从源码种可以看出,主要通过上面这三种方法。1、字符流。2、字节流。3、Configuration类实例作为入参。

通过上面源码不难看出,不管是字符流还是字节流最后都是指向了第三种方法。

 

那么SqlSessionFactory的基本构建流程其实也就比较明了了。

配置文件--->SqlSessionFactorybuild-->XMLConfigBuilder-->Configuration-->DefaultSqlSessionFactory

其实也就是SqlSessionFactorybuild读取配置文件后,先通过XMLConfigBuilder生产出Configuration类实例对象。

XMLConfigBuilder源码

public XMLConfigBuilder(InputStream inputStream, String environment, Properties props) {

    this(new XPathParser(inputStream, true, props, new XMLMapperEntityResolver()), environment, props);

}

private XMLConfigBuilder(XPathParser parser, String environment, Properties props) {

    super(new Configuration());

    ErrorContext.instance().resource("SQL Mapper Configuration");

    this.configuration.setVariables(props);

    this.parsed = false;

    this.environment = environment;

    this.parser = parser;

}

public Configuration parse() {

    if (this.parsed) {

        throw new BuilderException("Each XMLConfigBuilder can only be used once.");

    } else {

        this.parsed = true;

        this.parseConfiguration(this.parser.evalNode("/configuration"));

        return this.configuration;

    }

}

private void parseConfiguration(XNode root) {

    try {

        this.propertiesElement(root.evalNode("properties"));

        this.typeAliasesElement(root.evalNode("typeAliases"));

        this.pluginElement(root.evalNode("plugins"));

        this.objectFactoryElement(root.evalNode("objectFactory"));

        this.objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));

        this.settingsElement(root.evalNode("settings"));

        this.environmentsElement(root.evalNode("environments"));

        this.databaseIdProviderElement(root.evalNode("databaseIdProvider"));

        this.typeHandlerElement(root.evalNode("typeHandlers"));

        this.mapperElement(root.evalNode("mappers"));

    } catch (Exception var3) {

        throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + var3, var3);

    }

}

 

DefaultSqlSessionFactory源码

//

// Source code recreated from a .class file by IntelliJ IDEA

// (powered by Fernflower decompiler)

//

package org.apache.ibatis.session.defaults;

import java.sql.Connection;

import java.sql.SQLException;

import org.apache.ibatis.exceptions.ExceptionFactory;

import org.apache.ibatis.executor.ErrorContext;

import org.apache.ibatis.executor.Executor;

import org.apache.ibatis.mapping.Environment;

import org.apache.ibatis.session.Configuration;

import org.apache.ibatis.session.ExecutorType;

import org.apache.ibatis.session.SqlSession;

import org.apache.ibatis.session.SqlSessionFactory;

import org.apache.ibatis.session.TransactionIsolationLevel;

import org.apache.ibatis.transaction.Transaction;

import org.apache.ibatis.transaction.TransactionFactory;

import org.apache.ibatis.transaction.managed.ManagedTransactionFactory;

public class DefaultSqlSessionFactory implements SqlSessionFactory {

    private final Configuration configuration;

    public DefaultSqlSessionFactory(Configuration configuration) {

        this.configuration = configuration;

    }

    public SqlSession openSession() {

        return this.openSessionFromDataSource(this.configuration.getDefaultExecutorType(), (TransactionIsolationLevel)null, false);

    }

    public SqlSession openSession(boolean autoCommit) {

        return this.openSessionFromDataSource(this.configuration.getDefaultExecutorType(), (TransactionIsolationLevel)null, autoCommit);

    }

 

    public SqlSession openSession(ExecutorType execType) {

        return this.openSessionFromDataSource(execType, (TransactionIsolationLevel)null, false);

    }

    public SqlSession openSession(TransactionIsolationLevel level) {

        return this.openSessionFromDataSource(this.configuration.getDefaultExecutorType(), level, false);

    }

    public SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level) {

        return this.openSessionFromDataSource(execType, level, false);

    }

    public SqlSession openSession(ExecutorType execType, boolean autoCommit) {

        return this.openSessionFromDataSource(execType, (TransactionIsolationLevel)null, autoCommit);

    }

    public SqlSession openSession(Connection connection) {

        return this.openSessionFromConnection(this.configuration.getDefaultExecutorType(), connection);

    }

    public SqlSession openSession(ExecutorType execType, Connection connection) {

        return this.openSessionFromConnection(execType, connection);

    }

    public Configuration getConfiguration() {

        return this.configuration;

    }

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

        Transaction tx = null;

        DefaultSqlSession var8;

        try {

            Environment environment = this.configuration.getEnvironment();

            TransactionFactory transactionFactory = this.getTransactionFactoryFromEnvironment(environment);

            tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);

            Executor executor = this.configuration.newExecutor(tx, execType);

            var8 = new DefaultSqlSession(this.configuration, executor, autoCommit);

        } catch (Exception var12) {

            this.closeTransaction(tx);

            throw ExceptionFactory.wrapException("Error opening session.  Cause: " + var12, var12);

        } finally {

            ErrorContext.instance().reset();

        }

        return var8;

    }

    private SqlSession openSessionFromConnection(ExecutorType execType, Connection connection) {

        DefaultSqlSession var8;

        try {

            boolean autoCommit;

            try {

                autoCommit = connection.getAutoCommit();

            } catch (SQLException var13) {

                autoCommit = true;

            }

            Environment environment = this.configuration.getEnvironment();

            TransactionFactory transactionFactory = this.getTransactionFactoryFromEnvironment(environment);

            Transaction tx = transactionFactory.newTransaction(connection);

            Executor executor = this.configuration.newExecutor(tx, execType);

            var8 = new DefaultSqlSession(this.configuration, executor, autoCommit);

        } catch (Exception var14) {

            throw ExceptionFactory.wrapException("Error opening session.  Cause: " + var14, var14);

        } finally {

            ErrorContext.instance().reset();

        }

        return var8;

    }

    private TransactionFactory getTransactionFactoryFromEnvironment(Environment environment) {

        return (TransactionFactory)(environment != null && environment.getTransactionFactory() != null ? environment.getTransactionFactory() : new ManagedTransactionFactory());

    }

    private void closeTransaction(Transaction tx) {

        if (tx != null) {

            try {

                tx.close();

            } catch (SQLException var3) {

            }

        }

    }

}

 

DefaultSqlSessionFactory只有一个属性Configuration和一个构造方法。

从源码看出DefaultSqlSessionFactory最后还是调用openSessionFromDataSource或者openSessionFromConnection的。

openSessionFromDataSource

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

    Transaction tx = null;

    DefaultSqlSession var8;

    try {

        Environment environment = this.configuration.getEnvironment();

        TransactionFactory transactionFactory = this.getTransactionFactoryFromEnvironment(environment);

        tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);

        Executor executor = this.configuration.newExecutor(tx, execType);

        var8 = new DefaultSqlSession(this.configuration,configuration, autoCommit);

    } catch (Exception var12) {

        this.closeTransaction(tx);

        throw ExceptionFactory.wrapException("Error opening session.  Cause: " + var12, var12);

    } finally {

        ErrorContext.instance().reset();

    }

    return var8;

}

 

此方法执行的大致流程

1、先用configuration的environment对象去构造一个工厂transactionFactory。

2、然后再用transactionFactory工厂得到一个新对象Transaction,

3、再用新对象tx和execType去构建另一个对象executor。

4、最后configuration、configuration、autoCommit一起构造DefaultSqlSessionFactory。

openSessionFromConnection

private SqlSession openSessionFromConnection(ExecutorType execType, Connection connection) {

        DefaultSqlSession var8;

        try {

            boolean autoCommit;

            try {

                autoCommit = connection.getAutoCommit();

            } catch (SQLException var13) {

                autoCommit = true;

            }

            Environment environment = this.configuration.getEnvironment();

            TransactionFactory transactionFactory = this.getTransactionFactoryFromEnvironment(environment);

            Transaction tx = transactionFactory.newTransaction(connection);

            Executor executor = this.configuration.newExecutor(tx, execType);

            var8 = new DefaultSqlSession(this.configuration, executor, autoCommit);

        } catch (Exception var14) {

            throw ExceptionFactory.wrapException("Error opening session.  Cause: " + var14, var14);

        } finally {

            ErrorContext.instance().reset();

        }

        return var8;

    }

 

这个和上谜案的大致一致,不一样的就是

1、此方法首先从connection中获取到autoCommit。

2、在用transactionFactory工厂得到一个新对象Transaction时用connection作为参数。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值