转载

MyBatis 的秘密(五)整体流程图

执行流程图

通过前面的分析,我们梳理了 MyBatis 从调用方法到返回结果的整个流程,这里我们简单的做一个总结:

MyBatis 的秘密(五)整体流程图

先上图,按道理来说时序图应该是最合适的,但是我觉得上面的文字过多。接下来结合上面的图详细说说 MyBatis 从启动到返回结果的流程。

  • 首先,使用 SqlSessionFactoryBuilder 读取 MyBatisXML 配置文件,并解析配置,生成 Configuration 对象,返回 SqlSessionFactory

    调用 build 方法可以传递 Environment 选择使用的环境

    同时可以执行 Properties ,并且此 Properties 的优先级最高

  • 通过 SqlSessionFactory 可以获取 SqlSession , SqlSessionFactory 的作用如其名字所示,根据不同参数产生 SqlSession

    同理,通过 SqlSessionFactory 获取 SqlSession 的时候,也可以传递一下参数:

    • ExecutorType : 选择使用的 Executor , 默认为 SIMPLE
    • AutoCommit : 是否开启事务

    还有其他的比如事务级别等

    注意:虽然这里可以指定是否开启事务,但是具体真的是否开启事务,还是由实现了 MyBatisTransaction 接口的事务管理器处理,不一定是真正的开启了事务

  • 获取到 SqlSession 后,便可以调用想要执行的 MapperSqlSession 对应的方法被调用后,会简单的处理参数,将参数装化为 Executor 需要的类型

    对于 Executor 来说, SQL 就分两种,即查找( query() )和修改( update() ) ,我们使用的 SqlSession 中个中方法,最终都会被转换为这两种形式,然后调用 Executor

    当使用 Select 的时候,可以传递一个 ResultHanlder ,自行处理结果

  • Executor 被调用后,会根据所配置的 Statement ,创建不同的 StatmentHandler ,然后将 SQL 交给 StatmentHandler 处理

    ExecutorMyBatis 中有4种实现,其中可以配置的分别是 SIMPLE , REUSE , BATCH ,默认为 SIMPLE ,其中 REUSE 会缓存创建的 StatmentHandler , BATCH 底层调用的是 JDBC#batch() 方法

    另外一种是其他 Executor 的包装类: CachingExecutor ,当开启了二级缓存的时候,默认会先使用 CachingExecutor 进行查找,当无法查找成功的时候,再委托给后面3种 Executor 进行查找

    StatementHandlerMyBatis 中有3种实现,可以配置的是 PREPARED , STATEMENT , CALLABLE ,分别对应 JDBC 中的 PreparedStatmentStatement , CallableStatment

    通过这一步, Executor 会初始化 StatmentHandler 所有参数,比如参数(通过 TypeHandler 设置),超时时间, FetchSize

  • StatementHandler 被调用后,就会真正的执行 SQL ,在执行完毕后,对于 update() ,则直接返回被影响的行数,如果需要返回自增长 id ,则使用 KeyGenerator 查询 Id ,对于查询 select() ,则会交由 ResultSetHandler 逐行处理数据

    StatementHandler 所做的工作并不多,底层便是调用的真正的 JDBCStatement 工作,然后根据所执行的操作的不同,对结果进行不同的处理

  • StatmentHandler 获取到查询结果后,会调用 ResultSetHandler 处理结果, ResultSetHandler 会根据 XML 中所配置的方法进行结果处理,如果没有嵌套结果,则进行简单处理,如果还有动态嵌套,并且 设置了延迟加载 ,那么 ResultSetHandler 会通过 CGLIB (默认)或则 javassist 框架生成一个代理对象,当真正调用此方法的时候再去查询.

    ResultSetHandler 处理结果输入为 Statement ,输出为真正的结果,当 ResultSetHandler 获取到 Statement 的时候, Statement 已经执行了 execute() 方法,之所以说这么多,是因为后面的插件( Plugin ) 会使用到

    ResultSetHandler 在处理每一行数据的时候,都是通过调用 TypeHandler 加上反射完成 ORM ,当成功生成对象后再调用的 ResultHandler 进行额外的处理,不过默认的 DefaultResultHandler 并没有进行什么特殊的处理,

    MyBatis 允许我们自定义 ResultHandler 处理结果,不过限制为方法返回为 void

以上,便是 MyBatis 的整体调用流程,可以看出来算是 MyBatis 的代码分层分的非常细。以上这些逻辑代码,其实在一个类中都能完成。不过那样显得十分臃肿,而 MyBatis 却真正的体现出了面向对象的单一职责原则,依赖注入原则,从而基本能够做到开闭原则。

原文  http://dengchengchao.com/?p=1200
正文到此结束
Loading...