zoukankan      html  css  js  c++  java
  • MyBatis 源码篇-SQL 执行的流程

    本章通过一个简单的例子,来了解 MyBatis 执行一条 SQL 语句的大致过程是怎样的。

    案例代码如下所示:

    public class MybatisTest {
    
        @Test
        public void selectByPrimaryKey() throws IOException {
            // 3
            StudentDao studentDao = getSqlSession().getMapper(StudentDao.class);
            // 4
            Student student = studentDao.selectByPrimaryKey(1L);
            System.out.println(student);
        }
    
        /**
         * 获取SqlSession
         * 
         * @return
         */
        private SqlSession getSqlSession() throws IOException {
            // 1
            InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
            // 2
            return sqlSessionFactory.openSession(true);
        }
    }

    Configuration

    第一步,通过资源加载模块加载配置文件,解析器模块解析 XML 文件,生成 Configuration 对象。

    源码内容参考:org.apache.ibatis.session.SqlSessionFactoryBuilder#build(java.io.InputStream, java.lang.String, java.util.Properties) 方法

    深入 parse() 方法可以查看配置文件的具体解析过程,以及如何生成 Configuration 对象。

    Configuration 对象中缓存了 mybatis-config.xml 配置文件以及映射配置文件的所有内容。

    SqlSession

    第二步,通过 SqlSessionFactory 创建 SqlSession,SqlSession 是 MyBatis 暴露给外部使用的统一接口层,所有和数据库打交道的操作都通过 SqlSession 这层。

    下面通过时序图描述 SqlSession 对象的创建流程:

    MapperProxy

    第三步,通过 SqlSession 获得 StudentMapper 对象,为了便于理解,下面通过时序图描述 Mapper 对象的获取流程。

    MapperRegistry 是 Configuration 的一个属性,MapperRegistry 缓存了 MapperProxyFactory 的 Map 集合,也就是说在解析完配置文件后,knownMappers 集合数据已经在 Configuration 对象中存在了。

     

    问题一:为什么 StudentMapper(接口) 可以调用方法?

    通过断点调试来看看 StudentMapper 的真实对象是什么:

    MapperProxy 类的代码如下:

    MapperProxyFactory 的 newInstance 方法实现代码如下:

    通过上面的源码内容,可以得出如下结论:

    • StudentMapper 的真实对象是 MapperProxy;
    • MapperProxy 继承 InvocationHandler,实现 invoke 方法;
    • MapperProxyFactory 的 newInstance 方法,通过 JDK 动态代理的方式创建了一个 MapperProxy 的代理类;

    MyBatis 的 Mapper 是通过动态代理实现的,调用 Mapper 的任何方法都会执行 MapperProxy 的 invoke 方法。

    MyBatis 使用的动态代理和通常的动态代理有点区别,没有实现类,只有接口。

    动态代理类图结构如下所示:

    MyBatis 动态代理类图结构如下所示:

    selectByPrimaryKey

    第四部,执行 selectByPrimaryKey 查询学生信息。在第8行代码上面打上断点,调试选择“step into”,进入子函数内部,调用 org.apache.ibatis.binding.MapperProxy#invoke 方法。

    MapperMethod 通过如下方式创建。

    • mapperInterface:interface com.yjw.mybatis.dao.StudentMapper;
    • method:invoke 方法中传进来的 method 类;
    • Configuration:MyBatis 的核心类,所有配置信息都存在该类中;

    接着执行 mapperMethod.execute(sqlSession, args) 方法。

    接下来还是走到 SqlSession 类中,调用 selectOne 方法。继续往下执行,会执行 Executor 的 query 方法。

    通过上面的分析,简单总结一下,我们可以抽象出 MyBatis 在执行一条 SQL 查询的过程中涉及到的主要类:Configuration、SqlSession、MapperProxy、Exector,根据这些类画出如下 MyBatis 执行 SQL 的时序图:

    • 第一步是获取 MapperProxy 代理对象;
    • 第二步是根据获取的代理对象,执行查询操作;

    Exector

    SqlSession 中的 JDBC 操作部分最终都会委派给 Exector 实现,接着上面的断点往下执行,进入 Exector 的 query 方法。

    下面通过时序图描述 Exector 的执行流程,真实的调用链路类比较多,这里简化了调用链路,省略了一些装饰类、代理类,便于理解:

    根据 Exector 执行的时序图,可以抽象出的主要类是:SqlSession、Exector、StatementHandler、ParameterHandler、ResultSetHandler。

    StatementHandler 接口是 MyBatis 的核心接口之一,它是 Exector 接口实现的基础。StatementHandler 的主要功能很多,例如创建 Statement 对象,为 SQL 语句绑定实参,执行 SQL 语句,将结果集映射成结果对象。

    StatementHandler 类中包含了 ParameterHandler 和 ResultSetHandler 的属性。ParameterHandler 的主要功能是为 SQL 语句绑定实参,也就是使用传入的参数替换 SQL 语句中的“?”占位符。ResultSetHandler 的主要功能是将结果集映射成结果对象。

    参考 BaseStatementHandler 类:org.apache.ibatis.executor.statement.BaseStatementHandler

    结论

    根据上面的分析,抽象出的主要类有:Configuration、SqlSession、MapperProxy、Exector、StatementHandler、ParameterHandler、ResultSetHandler。

    MyBatis 源码篇

  • 相关阅读:
    WSP部署错误—SharePoint管理框架中的对象“SPSolutionLanguagePack Name=0”依赖其他不存在的对象
    Elevate Permissions To Modify User Profile
    Error with Stsadm CommandObject reference not set to an instance of an object
    ASP.NET MVC3添加Controller时没有Scaffolding options
    测试使用Windows Live Writer写日志
    配置TFS 2010出现错误—SQL Server 登录的安全标识符(SID)与某个指定的域或工作组帐户冲突
    使用ADO.NET DbContext Generator出现错误—Unable to locate file
    CSS
    HTML DIV标签
    数据库
  • 原文地址:https://www.cnblogs.com/yinjw/p/11757349.html
Copyright © 2011-2022 走看看