zoukankan      html  css  js  c++  java
  • Mybatis-运行原理

    一、mybatis分层图

     

    二、运行流程

    根据全局配置文件创建sqlSessionFactory对象

    1. 根据全局配置文件的io流来构建SqlSessionFactoryBuilder对象:
    2. 解析(XmlConfigBuilder遍历全局配置文件的每一项节点)全局配置文件里的每一个配置项;每一个配置项都会调用相应的方法进行初始化,之后将这些构建好的配置对象保存到Configuration中;这些配置对象执行的步骤以<resource mapper>为例:
    3. 根据resource解析的信息拿到mapper映射文件的地址,加载mapper映射文件的io流;
    4. 解析(XmlMapperBuilder遍历mapper映射文件的每一项节点),这些项返回的结果对象都会保存到Configuration里;以select|update这些标签为例:
    5. 通过statementParser解析这些标签内的每一项并将这些信息保存到mappedstatement对象,再将mappedstatement保存到Configuration
    6. 通过configuration对象构建defaultSqlSessionFactory对象

    总结

      mybatis通过xpathparser(dom4j)将解析到的所有配置文件里的节点信息(生成相应的配置项对象)封装到configuration对象中,最终返回一个包含configuration的defaultSqlSessionFactory

     

    根据sqlSessionFactory对象获取sqlsession对象

    1. 在openSessionFromDataSource()中通过先前构建DefaultSqlSessionFactory对象时传入的configuration属性获取环境信息
    2. 根据环境信息里的数据源、事务隔离级别等信息构建事务对象
    3. 根据事务、执行器类型创建对用的SQL类型执行器Executor(SIMPLE、REUSE、BATCH)
    4. 判断是否开启了二级缓存来对先前创建的执行器进行一次包装(这样开启了缓存每次我们再次查询都会先用cacheExecutor对象的方法,查询不到则通过包装进给他的Executor对象再次查询)
    5. 使用插件再对我们的executor进行包装。。。。
    6. 通过构建好的executor对象和configuration对象返回DefaultSqlSession

    总结

      根据configuration获取环境信息创建事务对象,通过Transaction和ExecutorType创建Executor对象以及根据二级缓存、插件来进行多次包装,最终返回一个包含Executor和Configuration的DefaultSqlSession对象

     

    根据sqlsession对象获取接口的代理对象(MapperProxy)

    1. 先前构建sqlSessionFactory时在configuration对象中有个mapperRegistry对象,这个对象中有个map,它以接口的地址(接口类型)作为key,value为MapperProxyFactory
    2. 从configuration中调用mapperRegistry的getMapper(type,sqlSession),通过type去查找map中的key,返回含有具体接口类型的MapperProxyFactory
    3. MapperProxy代理对象通过MapperProxyFactory传入当前的sqlSession进行创建并返回

     

    执行增删改查方法

    1. getMapper()获取到的是mybatis为我们创建好的mapperProxy接口代理对象,invoke()会将我们的接口方法转为mybtis能识别的mapperMethod对象
    2. 首先判断方法的操作数据库类型(增删改查)、返回结果的数据结构,对参数进行重新包装(参考参数源码那一节),以查询对象为例:
    3. 调用sqlSession.one(),之后它还是会调用list();最终返回的对象从这个list集合里取第一个对象内容
    4. 调用executor.query(mappedStatement),从传入的mappedStatement中获取sql信息
    5. 判断session缓存是否有数据,没有就查询数据库
    6. 创建StatementHandler对象(preparedStatementHandler),根据插件进行包装
    7. 创建paramterHandler对象,根据插件进行包装
    8. 创建ResultSetHandler对象,根据插件进行包装
    9. 预编译sql产生PreparedStatement对象,调用paramterHandler设置参数(是通过TypeHander设置参数的)
    10. 执行查询后使用ResultSetHandler处理结果(通过TypeHander获取value)

    封装参数

      MapperProxy(InvocationHandler动态代理)→invoke()→mybatis会将我们的接口方法转换成一个MapperMethod­.class,之后执行execute();

      首先判断标签类型,如果是查询判断方法返回类型,以返回一个对象为例:  method.convertArgsToSqlCommandParam(args)→paramNameResolver.getNamedParams(args)→ParamNameResolver【构造器初始化了我们参数的key,他会判断方法体上是否有@param的注解,如果有则会按照paramIndex:注解标注的值组成一个treeMap,如果没有则是paramIndex:map.size,在jdk1.8版本能够获取参数名】→getNamedParams(args)【如果没用@param标注&&参数就1个,通过args[names.firstKey()]返回;如果是多个,通过获取names.value作为key、names.key作为args[]的下标;并且mybatis额外为我们通过param+ String.valueOf(i + 1)作为key方式获取】。

      多参数下也就是说我们如果定义了@param(“”)的话就用定义的参数名取值;没定义的话则要用#{paramIndex?0}(视频里没说,看源码发现的)或者#{param1}(下标i+1了)

    查询流程总结

       mybatis在初始化SqlSessionFactory对象的过程中,会为每个接口创建一个接口代理对象,并将这些信息保存在mapperRegistry(key是接口类型,value是接口代理对象工厂),之后在构建SqlSession中根据环境信息配置出事务对象,根据ExecutorType、事务隔离级别创建Executor,我们任何CRUD操作其实都是通过Executor去执行的;通过preparedStatementHandle创建preparedStatement(从mappedStatement获取到sql信息(key是namespace+methodId,value是每个标签内的所有信息)),而传入的参数和结果映射都是通过TypeHandler去设置的

     

    总结

    1. 根据配置文件(全局,sql映射)初始化出Configuration对象
    2. 创建一个DefaultSqlSession对象,里面包含Configuration以及Executor(根据全局配置文件中的defaultExecutorType创建出对应的Executor)
    3. DefaultSqlSession.getMapper()拿到Mapper接口对应的MapperProxy
    4. MapperProxy里面有(DefaultSqlSession)
    5. 执行增删改查方法:
      • 调用DefaultSqlSession的增删改查(Executor)
      • 会创建一个StatementHandler对象(同时也会创建出ParameterHandler和ResultSetHandler)
      • 调用StatementHandler预编译SQL以及使用ParameterHandler来给sql设置参数值;
      • 调用StatementHandler的增删改查方法
      • ResultSetHandler封装结果
        注意:四大对象每个创建的时候都有一个interceptorChain.pluginAll(parameterHandler);

     

    搞清楚每一步都做了什么工作,那么框架大致的流程及源码就了解的差不多了

     

  • 相关阅读:
    ireport制作小技巧
    Spring 自动装配 Bean
    Toad创建DBLINKsop
    Spring 读书笔记-----使用Spring容器(一)
    Spring读书笔记-----Spring的Bean之Bean的基本概念
    关于iOS开发中info.plist文件的解读
    iOS常用的第三方库GitHub地址
    NSUserDefault的使用
    论坛收集
    iOS开发的一些奇巧淫技
  • 原文地址:https://www.cnblogs.com/edda/p/13430778.html
Copyright © 2011-2022 走看看