Mybatis笔记6 SqlSessionFactory SqlSession Mapper源码分析

Mybatis流程步骤

a.获取SqlSessionFactory对象
b.获取SqlSession对象
c.获取Mapper对象(代理接口中的方法、mapper.xml中的标签)
d.执行标签中定义的SQL语句

SqlSessionFactory

  String resource = "conf.xml";
  InputStream inputStream = Resources.getResourceAsStream(resource);
  SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

Mybatis笔记6 SqlSessionFactory SqlSession Mapper源码分析_第1张图片
parser解析器
Mybatis笔记6 SqlSessionFactory SqlSession Mapper源码分析_第2张图片
通过parseConfiguration()configuration设置了 properties、settings,environments等属性标签
Mybatis笔记6 SqlSessionFactory SqlSession Mapper源码分析_第3张图片
解析setting标签
Mybatis笔记6 SqlSessionFactory SqlSession Mapper源码分析_第4张图片
解析mapper.xml标签
Mybatis笔记6 SqlSessionFactory SqlSession Mapper源码分析_第5张图片
解析sql标签
Mybatis笔记6 SqlSessionFactory SqlSession Mapper源码分析_第6张图片
将sql标签解析成MappedStatement对象
Mybatis笔记6 SqlSessionFactory SqlSession Mapper源码分析_第7张图片
通过MappedStatement属性可以发现,其就是sql标签的对象
Mybatis笔记6 SqlSessionFactory SqlSession Mapper源码分析_第8张图片
发现parse解析器解析后返回的是Configuration对象
Mybatis笔记6 SqlSessionFactory SqlSession Mapper源码分析_第9张图片
Mybatis笔记6 SqlSessionFactory SqlSession Mapper源码分析_第10张图片
查看Configuration,发现包含了所有的配置信息和MappedStatement对象
Mybatis笔记6 SqlSessionFactory SqlSession Mapper源码分析_第11张图片
返回Configuration对象后通过build方法返回一个DefaultSqlSessionFactory对象
Mybatis笔记6 SqlSessionFactory SqlSession Mapper源码分析_第12张图片
DefaultSqlSessionFactory是SqlSessionFactory的一个实现类,所有默认使用的sqlSessionFactory对象其实是DefaultSqlSessionFactory。

大致流程
Mybatis笔记6 SqlSessionFactory SqlSession Mapper源码分析_第13张图片

SqlSession

 SqlSession sqlSession = sqlSessionFactory.openSession();

在这里插入图片描述
openSession()调用openSessionFromDataSource
在这里插入图片描述
Mybatis笔记6 SqlSessionFactory SqlSession Mapper源码分析_第14张图片
通过Configuration获得执行器类型,并可以发现默认是SIMPLE.
Mybatis笔记6 SqlSessionFactory SqlSession Mapper源码分析_第15张图片

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

发现除了返回一个DefaultSqlSession(SqlSession的实现类,包含配置信息,执行器,事务)还通过Configuration对象生成了一个执行器
Mybatis笔记6 SqlSessionFactory SqlSession Mapper源码分析_第16张图片

 Executor executor = (Executor)this.interceptorChain.pluginAll(executor);

Configuration 通过不同的executorType和事务生成不同类型的执行器,并且会被拦截器/链(interceptorChain)拦截并装饰(pluginAll(executor))。

大致流程
openSession()->openSessionFromDataSource()->DefaultSqlSession对象

Mapper对象的获取和执行

在这里插入图片描述
在这里插入图片描述
Mybatis笔记6 SqlSessionFactory SqlSession Mapper源码分析_第17张图片
Mapper注册器,通过mapperProxyFactory生成mapperProxy
在这里插入图片描述
生成mapperProxy
在这里插入图片描述
MapperProxy对象
在这里插入图片描述
JDK动态代理接口
发现用到了动态代理模式用 MapperProxy代理对象执行sql操作

执行

Mybatis笔记6 SqlSessionFactory SqlSession Mapper源码分析_第18张图片

 MapperMethod mapperMethod = this.cachedMapperMethod(method);
 return mapperMethod.execute(this.sqlSession, args);

mapperMethod.execute(sqlSession,args) :实际调用增删改查的方法 ,依靠于sqlSession中的configurationexecutor
在这里插入图片描述
SqlSession(configuration,executor,事务)、
MapperInterface 代理接口的对象
methodCache(存放查询缓存, 底层是CurrentHashMap)

public Object execute(SqlSession sqlSession, Object[] args) {
        Object result;
        Object param;
        switch(this.command.getType()) {
        case INSERT:
            param = this.method.convertArgsToSqlCommandParam(args);
            result = this.rowCountResult(sqlSession.insert(this.command.getName(), param));
            break;
        case UPDATE:
            param = this.method.convertArgsToSqlCommandParam(args);
            result = this.rowCountResult(sqlSession.update(this.command.getName(), param));
            break;
        case DELETE:
            param = this.method.convertArgsToSqlCommandParam(args);
            result = this.rowCountResult(sqlSession.delete(this.command.getName(), param));
            break;
        case SELECT:
            if (this.method.returnsVoid() && this.method.hasResultHandler()) {
                this.executeWithResultHandler(sqlSession, args);
                result = null;
            } else if (this.method.returnsMany()) {
                result = this.executeForMany(sqlSession, args);
            } else if (this.method.returnsMap()) {
                result = this.executeForMap(sqlSession, args);
            } else if (this.method.returnsCursor()) {
                result = this.executeForCursor(sqlSession, args);
            } else {
                param = this.method.convertArgsToSqlCommandParam(args);
                result = sqlSession.selectOne(this.command.getName(), param);
                if (this.method.returnsOptional() && (result == null || !this.method.getReturnType().equals(result.getClass()))) {
                    result = Optional.ofNullable(result);
                }
            }
            break;
        case FLUSH:
            result = sqlSession.flushStatements();
            break;
        default:
            throw new BindingException("Unknown execution method for: " + this.command.getName());
        }

        if (result == null && this.method.getReturnType().isPrimitive() && !this.method.returnsVoid()) {
            throw new BindingException("Mapper method '" + this.command.getName() + " attempted to return null from a method with a primitive return type (" + this.method.getReturnType() + ").");
        } else {
            return result;
        }
    }

查询的直接实现

result = this.executeForMany(sqlSession, args);

因为例子是查询全体所以是executeForMany
Mybatis笔记6 SqlSessionFactory SqlSession Mapper源码分析_第19张图片

Object param = this.method.convertArgsToSqlCommandParam(args);

在这里插入图片描述
处理增删改查方法的参数:method.convertArgsToSqlCommandParam(args)
Mybatis笔记6 SqlSessionFactory SqlSession Mapper源码分析_第20张图片
如果参数是0个,reutrun null ;
如果参数是1,返回第一个 ;
如果有多个参数 放入map中
Mybatis笔记6 SqlSessionFactory SqlSession Mapper源码分析_第21张图片
在这里插入图片描述
Mybatis笔记6 SqlSessionFactory SqlSession Mapper源码分析_第22张图片
sqlSession.selectList 是借助于sqlSession的executor执行器查询的
在这里插入图片描述
执行器的查询
Mybatis笔记6 SqlSessionFactory SqlSession Mapper源码分析_第23张图片
boundSql :将我们写的SQL 和 参数值进行了拼接后的对象,即最终能被真正执行的SQL

CacheKey key = this.createCacheKey(ms, parameterObject, rowBounds, boundSql);

用于标识缓存项
Mybatis笔记6 SqlSessionFactory SqlSession Mapper源码分析_第24张图片

 list = this.delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);

delegate 是一个执行器

  public  List query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
        ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
        if (this.closed) {
            throw new ExecutorException("Executor was closed.");
        } else {
            if (this.queryStack == 0 && ms.isFlushCacheRequired()) {
                this.clearLocalCache();
            }

            List list;
            try {
                ++this.queryStack;
                list = resultHandler == null ? (List)this.localCache.getObject(key) : null;
                if (list != null) {
                    this.handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
                } else {
                    list = this.queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
                }
            } finally {
                --this.queryStack;
            }

            if (this.queryStack == 0) {
                Iterator var8 = this.deferredLoads.iterator();

                while(var8.hasNext()) {
                    BaseExecutor.DeferredLoad deferredLoad = (BaseExecutor.DeferredLoad)var8.next();
                    deferredLoad.load();
                }

                this.deferredLoads.clear();
                if (this.configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
                    this.clearLocalCache();
                }
            }

            return list;
        }
    }

delegate 的 query

list = this.queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);

如果缓存中没有要查询的内容,则进入数据库 真实查询:queryFromDatabase()
Mybatis笔记6 SqlSessionFactory SqlSession Mapper源码分析_第25张图片

Mybatis笔记6 SqlSessionFactory SqlSession Mapper源码分析_第26张图片
StatementHandler处理器
在这里插入图片描述
发现默认是RoutingStatementHandler
Mybatis笔记6 SqlSessionFactory SqlSession Mapper源码分析_第27张图片

this.delegate = new PreparedStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);

进入 PreparedStatementHandler
Mybatis笔记6 SqlSessionFactory SqlSession Mapper源码分析_第28张图片
在这里插入图片描述
像传统JDBC操作
mybatis使用的jdbc对象是PreparedStatement
底层执行增删改查:PreparedStatement的execute()

 return this.resultSetHandler.handleResultSets(ps);

resultSetHandler处理器
Mybatis笔记6 SqlSessionFactory SqlSession Mapper源码分析_第29张图片
处理结果集

MyBatis底层在执行CRUD时 可能会涉及到四个处理器:StatementHandler ParameterHandler TypeHandler ResultSetHandler

大概流程
Mybatis笔记6 SqlSessionFactory SqlSession Mapper源码分析_第30张图片

你可能感兴趣的:(mybatis,数据库,sql,java)