mybatis源码阅读-SqlSessionFactory

Posted 意犹未尽

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mybatis源码阅读-SqlSessionFactory相关的知识,希望对你有一定的参考价值。

说明

读了3遍:https://my.oschina.net/zudajun/blog/665956 现在统一整理成笔记 并跟着源码一行一行调试 统一整理起来

SqlSession

接口定义

public interface SqlSession extends Closeable {
    <T> T selectOne(String var1);

    <T> T selectOne(String var1, Object var2);

    <E> List<E> selectList(String var1);

    <E> List<E> selectList(String var1, Object var2);

    <E> List<E> selectList(String var1, Object var2, RowBounds var3);

    <K, V> Map<K, V> selectMap(String var1, String var2);

    <K, V> Map<K, V> selectMap(String var1, Object var2, String var3);

    <K, V> Map<K, V> selectMap(String var1, Object var2, String var3, RowBounds var4);

    <T> Cursor<T> selectCursor(String var1);

    <T> Cursor<T> selectCursor(String var1, Object var2);

    <T> Cursor<T> selectCursor(String var1, Object var2, RowBounds var3);

    void select(String var1, Object var2, ResultHandler var3);

    void select(String var1, ResultHandler var2);

    void select(String var1, Object var2, RowBounds var3, ResultHandler var4);

    int insert(String var1);

    int insert(String var1, Object var2);

    int update(String var1);

    int update(String var1, Object var2);

    int delete(String var1);

    int delete(String var1, Object var2);

    void commit();

    void commit(boolean var1);

    void rollback();

    void rollback(boolean var1);

    List<BatchResult> flushStatements();

    void close();

    void clearCache();

    Configuration getConfiguration();

    <T> T getMapper(Class<T> var1);

    Connection getConnection();
}

完成数据库CRUD操作

 

实现类结构图

DefaultSqlSession部分源码 

 //执行器 接口
    private Executor executor;
    //配置文件 类
    private Configuration configuration;
    /***
     * 查询方法
     * @param statement mapper.xml namesapce+id
     * @param parameter 查询参数
     * @param rowBounds 分页参数 解析返回值的handler
     */
    public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
        List var5;
        try {
            //从config根据 namesapce+id 获得对应的mappedStatement 然后交给executor的query方法
            MappedStatement ms = this.configuration.getMappedStatement(statement);
            var5 = this.executor.query(ms, this.wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
        } catch (Exception var9) {
            throw ExceptionFactory.wrapException("Error querying database.  Cause: " + var9, var9);
        } finally {
            ErrorContext.instance().reset();
        }

        return var5;
    }
    /**
     * 修改方法 增加删除也是最终调用这个方法
     * @param statement mapper.xml namesapce+id
     * @param parameter 参数
     * @return
     */
    public int update(String statement, Object parameter) {
        int var4;
        try {
            this.dirty = true;
            //从config根据 namesapce+id 获得对应的mappedStatement 然后交给executor的query方法
            MappedStatement ms = this.configuration.getMappedStatement(statement);
            var4 = this.executor.update(ms, this.wrapCollection(parameter));
        } catch (Exception var8) {
            throw ExceptionFactory.wrapException("Error updating database.  Cause: " + var8, var8);
        } finally {
            ErrorContext.instance().reset();
        }

        return var4;
    }

 

职责是根据namesapce+id 获得对应的mappedStatement然后交给executor执行

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();
}

sqlSession工厂

类图

DefaultSqlSessionFactory源码

public class DefaultSqlSessionFactory implements SqlSessionFactory {
    //配置文件 保存了解析的mybaits.xml和mapper.xml的内容
    private final Configuration configuration;

    /**
     * openSession()最终都是调用这个方法创建Session
     * @param execType 执行器
     * @param level 事物隔离级别
     * @param autoCommit 是否自动提交
     * @return
     */
    private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
        Transaction tx = null;

        DefaultSqlSession var8;
        try {
            //根据配置文件获得Environment 内部封装了数据源信息和事物管理器Factory  environments标签配置
            Environment environment = this.configuration.getEnvironment();
            //获得对应的事物管理器
            TransactionFactory transactionFactory = this.getTransactionFactoryFromEnvironment(environment);
            //开启事物
            tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
            //创建执行器
            Executor executor = this.configuration.newExecutor(tx, execType);
            //创建DefaultSqlSession
            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;
    }

    /**
     * 判断是否有指定事物管理创建工厂 如果没有指定 则默认ManagedTransactionFactory environments标签配置
     * @param environment
     * @return
     */
    private TransactionFactory getTransactionFactoryFromEnvironment(Environment environment) {
        return (TransactionFactory)(environment != null && environment.getTransactionFactory() != null ? environment.getTransactionFactory() : new ManagedTransactionFactory());
    }

}

 SqlSessionManager

使用

执行完后自动提交回滚 创建2个session

  public static void main(String[] args) throws FileNotFoundException {
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder
                .build(ClassLoader.getSystemResourceAsStream("mybatis.xml"));
        SqlSessionManager sqlSessionManager = SqlSessionManager.newInstance(sqlSessionFactory);
        List<Classes> list = sqlSessionManager.selectList("classes.selectAll");
        list = sqlSessionManager.selectList("classes.selectAll");
    }

 

创建一个session手动提交回滚

public static void main(String[] args) throws FileNotFoundException {
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder
                .build(ClassLoader.getSystemResourceAsStream("mybatis.xml"));
        SqlSessionManager sqlSessionManager=null;
        try {
            sqlSessionManager.startManagedSession();
            List<Classes> list = sqlSessionManager.selectList("classes.selectAll");
            list = sqlSessionManager.selectList("classes.selectAll");
            sqlSessionManager.commit();
        }catch (Exception e) {
            if(sqlSessionManager!=null) {
                sqlSessionManager.rollback();
            }
        }
    }

 

类图

源码

public class SqlSessionManager implements SqlSessionFactory, SqlSession {
    private final SqlSessionFactory sqlSessionFactory;
    //被代理的sqlSeesion
    private final SqlSession sqlSessionProxy;
    //线程缓存
    private ThreadLocal<SqlSession> localSqlSession = new ThreadLocal();

    private SqlSessionManager(SqlSessionFactory sqlSessionFactory) {
        this.sqlSessionFactory = sqlSessionFactory;
        //代理sqlSession 第一个参数类装载器 第二个参数哪个接口类型被代理  第三个参数为代理类 为SqlSessionManager内部内
        this.sqlSessionProxy = (SqlSession) Proxy.newProxyInstance(SqlSessionFactory.class.getClassLoader(), new Class[]{SqlSession.class}, new SqlSessionManager.SqlSessionInterceptor());
    }

    public <T> T selectOne(String statement, Object parameter) {
        return this.sqlSessionProxy.selectOne(statement, parameter);
    }

    public int insert(String statement) {
        return this.sqlSessionProxy.insert(statement);
    }

    public int update(String statement, Object parameter) {
        return this.sqlSessionProxy.update(statement, parameter);
    }

    public int delete(String statement) {
        return this.sqlSessionProxy.delete(statement);
    }
  public SqlSession openSession() {
return this.sqlSessionFactory.openSession();
  }
}

内部类SqlSessionInterceptor源码

 private class SqlSessionInterceptor implements InvocationHandler {
        public SqlSessionInterceptor() {
        }

        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            //从当前线程获得SqlSession 如果为空则创建不为空则直接使用缓存中的SqlSession
            SqlSession sqlSession = (SqlSession)SqlSessionManager.this.localSqlSession.get();
            if (sqlSession != null) {
                try {
                    //直接使用线程缓存中的SqlSession 并不提交不回滚
                    return method.invoke(sqlSession, args);
                } catch (Throwable var12) {
                    throw ExceptionUtil.unwrapThrowable(var12);
                }
            } else {
                //调用SqlSessionManager的openSession方法获得SqlSession 执行完毕后提交回滚
                SqlSession autoSqlSession = SqlSessionManager.this.openSession();

                Object var7;
                try {
                    Object result = method.invoke(autoSqlSession, args);
                    autoSqlSession.commit();
                    var7 = result;
                } catch (Throwable var13) {
                    autoSqlSession.rollback();
                    throw ExceptionUtil.unwrapThrowable(var13);
                } finally {
                    autoSqlSession.close();
                }

                return var7;
            }
        }
    }

 

以上是关于mybatis源码阅读-SqlSessionFactory的主要内容,如果未能解决你的问题,请参考以下文章

spring整合MyBatis思路

mybatis源码阅读-helloword

手把手带你阅读Mybatis源码缓存篇

Mybatis源码阅读之--整体执行流程

mybatis源码阅读-SqlSessionFactory

mybatis源码阅读mybatis与spring整合原理