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

在这里插入图片描述
parser解析器
在这里插入图片描述
通过parseConfiguration()configuration设置了 properties、settings,environments等属性标签
在这里插入图片描述
解析setting标签
在这里插入图片描述
解析mapper.xml标签
在这里插入图片描述
解析sql标签
在这里插入图片描述
将sql标签解析成MappedStatement对象
在这里插入图片描述
通过MappedStatement属性可以发现,其就是sql标签的对象
在这里插入图片描述
发现parse解析器解析后返回的是Configuration对象
在这里插入图片描述
在这里插入图片描述
查看Configuration,发现包含了所有的配置信息和MappedStatement对象
在这里插入图片描述
返回Configuration对象后通过build方法返回一个DefaultSqlSessionFactory对象
在这里插入图片描述
DefaultSqlSessionFactory是SqlSessionFactory的一个实现类,所有默认使用的sqlSessionFactory对象其实是DefaultSqlSessionFactory。

大致流程
在这里插入图片描述

SqlSession

 SqlSession sqlSession = sqlSessionFactory.openSession();

在这里插入图片描述
openSession()调用openSessionFromDataSource
在这里插入图片描述
在这里插入图片描述
通过Configuration获得执行器类型,并可以发现默认是SIMPLE.
在这里插入图片描述

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

发现除了返回一个DefaultSqlSession(SqlSession的实现类,包含配置信息,执行器,事务)还通过Configuration对象生成了一个执行器
在这里插入图片描述

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

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

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

Mapper对象的获取和执行

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
Mapper注册器,通过mapperProxyFactory生成mapperProxy
在这里插入图片描述
生成mapperProxy
在这里插入图片描述
MapperProxy对象
在这里插入图片描述
JDK动态代理接口
发现用到了动态代理模式用 MapperProxy代理对象执行sql操作

执行

在这里插入图片描述

 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
在这里插入图片描述

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

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

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

用于标识缓存项
在这里插入图片描述

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

delegate 是一个执行器

  public <E> List<E> 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()
在这里插入图片描述

在这里插入图片描述
StatementHandler处理器
在这里插入图片描述
发现默认是RoutingStatementHandler
在这里插入图片描述

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

进入 PreparedStatementHandler
在这里插入图片描述
在这里插入图片描述
像传统JDBC操作
mybatis使用的jdbc对象是PreparedStatement
底层执行增删改查:PreparedStatement的execute()

 return this.resultSetHandler.handleResultSets(ps);

resultSetHandler处理器
在这里插入图片描述
处理结果集

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

大概流程
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值