Mybatis工作原理

287 阅读4分钟

「这是我参与11月更文挑战的第21天,活动详情查看:2021最后一次更文挑战」。

工作原理概览

image.png

  1. 首先会加载mybatis配置文件,然后进行解析,生成Configuration和一个个MappedStatement

  2. SqlSessionFactoryBuilder通过Configuration对象生成SqlSessionFactory,用来开启SqlSession.

  3. SqlSession对象完成和数据库的交互

  4. 当用户程序调用myatis接口层api(即Mapper接口的中的方法)

  5. SqlSession通过调用api的statement ID 找到对应的Mappedtatment对象

  6. 通过Executor(负责动态SQL生成和查询缓存的维护)将MappedStatement对象进行解析,sql参数转化,动态sql拼接,生成jdbc statment对象

  7. jdbc执行sql

  8. 借助MappedStatement中的结果映射关系,将返回结果转化为bean,map等结构

Mybatis核心类

SqlSessionFactoryBuilder

每一个Mybatis的应用程序的入口是SqlSessionFactoryBuilder.

它的作用就是通过XML文件创建Configuration对象。然后通过build方法创建

SqlSessionFactory对象。

image.png

SqlSessionFactoryBuilder根据传入的数据流生成Configuration对象,然后根据Configuration对象

创建默认的SqlSessionFactory实例。

Configuration

存储配置信息的容器并且Mapperstate对象以及Mapper接口的工厂类MapperProxyFactory都是再这个配置类中.

SqlSessionFactory

它的主要功能就是创建SqlSession对象,和SqlSessionFactoryBuilder对象一样,没有必要每次访问都创建一次,通常做法是创建一个全局的对象。

SqlSession

SqlSession对象主要功能是完成一次数据库的访问和结果的映射,它类似于数据库的session概念,由于不是线程安全的,所以SqlSession对象的作用域需限制方法内。

SqlSession主要由四个很重要的对象:

  • Execute: 调度执行StatementHandler、ParmmeterHandler、ResultHandler执行相应的SQL语句。

  • StatementHandler:使用数据库中Statement(PrepareStatement)执行操作,即底层是封装好了的prepareStatement。·

  • ParammeterHandler:处理SQL参数;

  • ResultHandler:结果集ResultSet封装处理返回。

Executer

执行器是真正执行java和数据库交互的东西,参与了整个sql查询执行过程。

Executor会先调用StatementHandler的prepare()方法预编译SQL语句,同时设置一些基本的运行参数,然后调用StatementHandler的parameterize()方法(实际上是启用了ParameterHandler设置参数)设置参数,resultHandler再组装查询结果返回调用者完成一次查询完成预编译,简单总结起来就是即先预编译SQL语句,之后设置参数(跟JDBC的prepareStatement过程类似)最后如果有查询结果就会组装返回。

getMapper

这个方法是用来获取Mapper接口的代理对象,我们都知道,如果是使用xml+mapper接口形式的映射器,那么mybatis是如何根据接口找到对应的sql去执行的呢,就是通过getMapper方法。

Mapper接口是个接口,不能实例化,那么怎么去执行,这时候就是通过动态代理。

通过getMapping方法,这个方法会调用configuration的getMapper方法,从configuration内部获取指定的Mapper接口类型的MapperProxy代理对象。

image.png

这个mapperRegistry是Configuration中的一个属性,,它内部维护一个HashMap用于存放mapper接口的工厂类,每个接口都会对应一个工厂类MapperProxyFactory.

然后通过这个工厂类拿到对应的Mapper接口,但拿到的是它的代理类MapperProxy。

image.png

这个类实现了JDK动态代理必须实现的InvocationHandler接口,我们知道,在jdk动态代理中,会回调

invoke方法,通过代码可以看到,在这个方法中,首先会拿到MapperMethod类,而真正去将接口和sql去匹配以及执行sql就是通过MapperMethod类。

MapperMethod类是整个代理机制的核心类,对sqlSession操作进行了封装使用,该类有两个内部类,SqlCommand和MethodSignature,SqlCommand用来封装CRUD操作,也就是我们在xml文件中配置的节点,每个节点都会生成对应的MapperStatement类,这个类是在xml解析的时候就生成了,而找到MapperStatement和接口方法的对应就是通过下面的代码去实现

image.png

首先要了解的一点是MapperStatement是存在Configuration中的MapperStatements这个Map集合中,集合的value存的是mapperstatement,.key存的是statementId,这个id是由mapper接口名,和方法名组成,所以接口和mapperstatement就是通过这种方式去匹配,回想下Mapper.xml的配置,每个Mapper.xml都要设置nameSpace,这个就是mapper接口名,每个sql都有一个id,这个id对应的就是

接口的方法名。

找到之后就会调用sqlSession的不同的具体方法去执行sql了。