4步带你看懂SqlSession是如何执行Mapper过程的

Mapper由两部分组成,分别为Mapper接口和通过注释或者XML文件配置的SQL语句。SqlSession 执行Mapper过程可以分为四步:Mapper接口注册、MappedStatement注册、Mapper方法调用、SqlSession 执行Mapper。

Mapper接口注册

Mybatis 通过Configuration 类中定义的mapperRegistry属性注册Mapper接口,调用MapperRegistry对象的addMapper()方法将Mapper接口信息和对应的MapperProxyFactory对象注册到MapperRegistry对象中。

在Configuration 类中定义mapperRegistry属性的代码如下:

protected final MapperRegistry mapperRegistry = new MapperRegistry(this);

getMapperRegistry()方法来完成注册:
在这里插入图片描述
MapperRegistry提供了addMapper()方法,用于向knownMappers属性中注册Mapper接口信息。在addMapper()方法中,为每个Mapper接口对应的Class对象创建一个MapperProxyFactory对象,然后添加到knownMappers属性中。MapperRegistry还提供了getMapper()方法,能够根据Mapper接口的Class对象获取对应的MapperProxyFactory对象,然后就可以使MapperProxyFactory对象创建Mapper动态代理对象了。MapperRegistry核心代码如下:
在这里插入图片描述

MappedStatement对象注册到Configuration对象

SQL配置有两种方式,一种是通过XML文件配置,另一种是通过java注解,而Mybatis 通过MappedStatement类描述Mapper的SQL配置信息。

在Configuration类中定义了mappedStatements属性用于注册Myabatis中所有的MappedStatement对象,mappedStatements的key为Mapper SQL 配置的id,如果SQL通过java注解配置,则id 为Mapper接口的完全限定名+方法名称。mappedStatements属性的定义如下:

 protected final Map<String, MappedStatement> mappedStatements = new StrictMap<MappedStatement>("Mapped Statements collection")
      .conflictMessageProducer((savedValue, targetValue) ->
          ". please check " + savedValue.getResource() + " and " + targetValue.getResource());

在Configuration类中提供了addMappedStatement()方法用于将MappedStatement对象添加到mappedStatement 属性中,代码如下:
在这里插入图片描述
想要明天mappedStatement对象的创建,需要重点关注的时候mybatis-config.xml 配置文件中的标签的解析,标签是通过XMLConfigBuilder的mapperElement()进行解析的。解析代码如下:
在这里插入图片描述
在mapperElement()方法中,先获取所有子标签,然后再根据不同的标签做不同的处理。

Mapper SQL 配置文件的解析是调用XMLMappedBuilder.parse()方法完成解析。解析代码如下:在这里插入图片描述
从方法中可知,调用了 configurationElement()方法对Mapper SQL配置文件的所有标签进行解析,标签解析的代码如下:
在这里插入图片描述
获取标签节点对应的XNode对象后,调用XMLMapperBuilder类的buildStatementFromContext()方法做进一步解析处理。
在这里插入图片描述
parseStatementNode()方法的代码比较长,总结起来做了五件事:
(1)获取<select|insert|delete|update>标签的所有属性信息。
(2)将标签引用的SQL片段替换为对应的标签中定义的内容。
(3)获取lang属性指定的LanguageDriver,通过LanguageDriver创建 SqlSource。MyBatis中的SqlSource表示一个SQL资源。
(4)获取KeyGenerator对象。KeyGenerator的不同实例代表不同的主键生成策略。
(5)所有解析工作完成后,使用MapperBuilderAssistant对象的
addMappedStatement()方法创建MappedStatement对象。创建完成后,调用Configuration对象的addMappedStatement()方法将MappedStatement对象注册到Configuration对象中。
parseStatementNode() 方法的源码如下:
在这里插入图片描述

Mapper方法调用

通过调用SqlSession对象的getMapper()方法获取动态代理对象,通过动态代理对象调用执行Mapper接口中定义的方法。代码如下:

    SqlSession sqlSession=sqlSessionFactory.openSession();
    OrderMapper orderMapper =sqlSession.getMapper(OrderMapper.class);
    List<Order> listOrder = orderMapper.findAllOrder();

此处使用的动态代理是JDK动态代理,根据JDK动态代理机制,MapperProxy实现了InvocationHandler接口,会重写Invoke()方法,重写代码如下:
在这里插入图片描述
在MapperMethod对象创建完成后,MapperMethod 提供了一个Executor()方法用于执行SQL命令,在execute()方法中,首先根据SqlCommand对象获取SQL语句的类型,然后根据SQL语句的类型调用SqlSession对象对应的方法。MyBatis通过动态代理将Mapper方法的调用转换成通过SqlSession提供的API方法完成数据库的增删改查操作。代码如下:
在这里插入图片描述

在这里插入图片描述

SqlSession 执行Mapper

SqlSession 接口只有一个默认的实现,即DefaultSqlSession。在DefaultSqlSession 中使用到策略模式,DefaultSqlSession扮演的是Context的角色,将所有数据库相关的操作全部封装到Executor接口职工实现,并通过executor字段选择不同的Executor实现。

以SqlSession定义的selectList()方法为例介绍SqlSession执行Mapper的过程。selectlist()的定义如下:

 <E> List<E> selectList(String statement);

在DefaultSqlSession中selectList()方法中,的具体实现如下:
在这里插入图片描述
在BaseExecutor类的query()方法中,首先从MappedStatement对象中获取BoundSql对象,BoundSgl类中封装了经过解析后的SQL语句及参数映射信息。然后创建CacheKey对象,该对象用于缓存的Key值。源代码如下:

在这里插入图片描述
在重载的query()方法中,首先从MyBatis一级缓存中获取查询结果,如果缓存中没有,则调用BaseExecutor类的queryFromDatabase()方法从数据库中查询。代码如下:

在这里插入图片描述

在queryFromDatabase()方法中,调用doQuery()方法进行查
询,然后将查询结果进行缓存,doQuery()是一个模板方法,由BaseExecutor子类实现。代码如下:
在这里插入图片描述

最后是调用Executor 的几个不同实现对返回结果进行处理,Mybatis通过调用Mapper接口定义的方法执行注解或者XML文件配置的SQL语句就完成。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

弯_弯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值