美文网首页
mybatis原理

mybatis原理

作者: laowangv2 | 来源:发表于2020-12-20 22:12 被阅读0次

    mybatis的运行流程

    一、原生用法

    1. 构建SqlSessionFactory

    String resource = "org/mybatis/example/mybatis-config.xml";
    InputStream inputStream = Resources.getResourceAsStream(resource);
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    

    在SqlSessionFactoryBuilder中,首先解析配置文件,得到Configuration,然后build new一个SqlSessionFactory返回:


    build

    看一下parse中具体做了哪些工作:


    parse
    mapperElement中会把解析出来的Mapper放到MapperRegistry中,以便后续使用。

    2. 创建SqlSession

    try (SqlSession session = sqlSessionFactory.openSession()) {
      Blog blog = (Blog) session.selectOne("org.mybatis.example.BlogMapper.selectBlog", 101);
    }
    

    最终委托到DefaultSqlSessionFactory的openSessionFromDataSource:


    创建SqlSession

    之后,一个集齐了executor,configuration的SqlSession就创建好了。

    3. 创建Mapper

    看一下SqlSession里getMapper的具体实现:


    getMapper

    委托给configuration后又委托给了mapperRegistry:


    mapperRegistry
    在第一步创建SqlSessionFactory的最后说过,在parse中会解析xml中的mapper并放入mapperRegistry中,现在就是取出来构建实例的时候了。并且传入了sqlSession,这样后续mapper中就可以把具体操作委托给sqlSession去完成。
    MapperProxyFactory
    MapperProxy

    接着就可以看到这里到了真正创建Mapper的时机,也看到Mapper的实现类MapperProxy,通过动态代理的方式创建出来。我们知道动态代理最终的方法会委托给InvocationHandler里,进到MapperProxy看一下,果不其然:


    MapperProxy
    最后在mapperMethod中,不出意外肯定会委托给sqlSession执行:
    MapperMethod
    好了,先到这里,后续在分析在SqlSession中的执行过程。

    二、让Spring管理一切

    1. SqlSessionFactoryBean

    把SqlSessionFactory注入到spring容器中

    @Configuration
    public class MyBatisConfig {
      @Bean
      public SqlSessionFactory sqlSessionFactory() {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(dataSource());
        return factoryBean.getObject();
      }
    }
    

    2. SqlSession同理

    @Configuration
    public class MyBatisConfig {
      @Bean
      public SqlSessionTemplate sqlSession() throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory());
      }
    }
    

    现在已经获得了和原生用法中一样的效果,并且更进一步,可以以注入的方式使用SqlSession了。

    3. Mapper

    实际使用中,显然不可能通过SqlSessionTemplate一个一个去getMapper,都是通过spring管理,直接注入使用。那么必然有地方把Mapper都加载起来纳入Spring管理。以@MapperScan为例分析其过程如下。

    MapperScannerRegistrar
    在MapperScannerRegistrar中,借助spring的能力扫描满足条件的mapper,并将其注入容器。具体参考https://blog.csdn.net/elim168/article/details/88131712
    doScan
    到这里已经可以看到,往spring容器里注入了mapper,class是MapperFactoryBean,对于FactoryBean,spring创建bean的时候会调用其getObject方法,进入MapperFactoryBean看一下
    MapperFactoryBean
    Ok,这样就和原生用法中的分析一致,回到了SqlSession的getMapper。
    一路看下来,我们可以看出来,引入spring-mybatis,其实就是把原来需要我们手动去操作mybatis的地方全部以spring的方式管理起来,我们只管用注入的方式去使用Mapper就好了。

    三、SqlSession如何操作数据库

    select
    MapperStatement从configuration中获取,最初在解析xml的时候会一并解析存入。
    然后交给executor执行,executor出现在openSessionFromDataSource时,默认类型是SimpleExecutor。继续跟踪,进入到基类BaseExecutor中:
    BaseExecutor
    首先从cache中提取,如果没有就进入queryFromDatabase,queryFromDatabase中又回到了Executor实现类的doQuery:
    doQuery
    在newStatementHandler中会把plugin插进去,prepareStatement会拿到一个connection,并编译statement,也就是使用jdbc时需要的那些操作,最后交由handler执行:
    PreparedStatementHandler
    这里默认的就是PreparedStatementHandler,也就是预编译PreparedStatement。

    mybatis架构

    mybatis主要构件

    对照图2


    mybatis架构设计

    参考
    深入理解mybatis原理

    相关文章

      网友评论

          本文标题:mybatis原理

          本文链接:https://www.haomeiwen.com/subject/pvmknktx.html