MyBatis+Springboot 启动到SQL执行全流程(1)

简介: MyBatis+Springboot 启动到SQL执行全流程

前言

本文我们将讲解Mybatis的动态sql是什么,以及如何解析,最终执行的全流程


一、MyBatis的Sql类型

1. 静态SQL

mybatis 静态sql 在编译期就已经确定其样子,就是可直接执行,或者填入参数即可执行的,如


SELECT * FROM users WHERE username = 'admin' AND password = #{password};

这种静态的sql在程序启动时,扫描到就可以生成对应的sqlsource。


2. 动态SQL

MyBatis的动态Sql是指在编写Sql语句时根据不同的条件动态地生成不同的Sql语句的技术。它可以根据不同的条件来选择不同的查询语句、修改语句、插入语句和删除语句等,减少了Sql语句的重复编写和维护成本,提高了Sql语句执行的效率。


MyBatis的动态Sql包括 if、choose、when、otherwise、trim、set、where、foreach 等标签,通过这些标签可以构建出多样化的Sql语句。因为语句最终样子不确定,需要根据入参的情况来动态生成不同样子的sql,所以叫动态sql


示例:

<select id="getUser" resultMap="UserMap">
  SELECT * FROM user
  <where>
    <if test="id != null">
      AND id = #{id}
    </if>
    <if test="name != null and name != ''">
      AND name = #{name}
    </if>
    <if test="age != null">
      AND age = #{age}
    </if>
  </where>
</select>
<insert id="addUser" parameterType="com.example.seeu.entity.User" >
        insert  into user(id,username,password) values
        <foreach collection="list" item="item" separator=",">
            (#{item.id}, #{item.username},#{item.password})
        </foreach>
</insert>

如上图,就是一段动态Sql,其中的 if 语句会先进行判断入参字段是否为空,如果不为空,才会在Sql中添加对应的的筛选条件;同时,我们也关注下 where 标签,这也是个动态标签,会帮我们检查筛选条件,帮我们补齐多个条件之间的 AND,如果是首条件前面带AND,也会自动帮我们去除。


二、流程1 —— 文件扫描并解析

1. 扫描xml文件

第一步肯定是先寻找,并加载到所有文件,但在此之前,我们必须配置好路径,否则Mybatis是无法加载到文件的。

#mybatis的相关配置
mybatis:
  #mapper配置文件【重点】
  mapper-locations: classpath:mapper/*.xml
  #开启驼峰命名
  configuration:
    map-underscore-to-camel-case: true
    cache-enabled: true

下图为SqlSessionFactoryBean.java 源码的主方法 buildSqlSessionFactory(),负责了遍历与解析xml的功能。

8ca960563f8345bbaf0f4737ad480fe7.png

我们这里强调两个步骤,

第一个就是命名空间绑定,这里主要是通过xml文件里的命名空间,找到其对应的Mapper接口,解析接口上的各类注解,最终将该Mapper接口及信息注册给Mybatis,需要注意的是,这里的注册与这些Mapper接口上的@Mapper注解无关,这里主要是收集Mapper实际的配置,注册进MyBatisConfiguration,最终会生成一个代理对象,并交由Mybatis管理和操作。而@Mapper则是一个桥梁,使得Spring容器也能获得该代理对象,进而在Spring的体系下,能使用上Mybatis的成果

第二个,就是对xml文件内容的解析,主要还是各个标签进行解析,我们下面会说到。

142aecda30e2411089694e38a3dc4788.png


2. 动态Sql解析

bfb5f5bc91ae48e2891ecd9b9646ae57.png

handler.handleNode 里面其实也调用 parseDynamicTags 方法,实现递归,此处实际上是将这些动态内容处理完后拼接成正常语法的Sql,如果嵌套的内容为动态,那么本层也标记为动态,注意,此时#{} 内容仅判断为动态SQL,并未做任何操作,所以拼接完仍然以#{} 形式存在

a4a36b3a35984ebc84fcf735adde2270.png

我们拿个简单的例子来说明

    <insert id="addUser" parameterType="com.zhanfu.springboot.demo.entity.User" >
        insert  into user(id,username,password) values
        <foreach collection="list" item="item">
            (#{item.id}, #{item.username},#{item.password})
        </foreach>
    </insert>

很明显,我们能看到这里面用了foreach标签,意味着是一个动态Sql,那么它最终会被解析成什么样呢?我们来看下图


492f0efd8e26442881bdeb220a9f0fe6.png

3. 保存解析结果

我们上面看到的最后,对每一个Mapper层的方法,都能解析出一个MappedStatement,这个东西最后会存在哪呢?其实它们会以Map的形式存在一个MyBatis单例配置类 Configuration 里。而这个配置类,毫无疑问也载入了容器中。

57a607bb4f904df29a510ac973465f2e.png

8a285874aafe4bd2ad2cc1fbd4842daa.png



目录
相关文章
|
27天前
|
设计模式 Java 容器
SpringBoot2 | SpringBoot启动流程源码分析(二)
SpringBoot2 | SpringBoot启动流程源码分析(二)
24 0
|
30天前
|
SQL Oracle 关系型数据库
整合Mybatis-Plus高级,Oracle 主键Sequence,Sql 注入器实现自定义全局操作
整合Mybatis-Plus高级,Oracle 主键Sequence,Sql 注入器实现自定义全局操作
76 0
|
1天前
|
缓存 Java 程序员
springboot的启动流程总结
springboot的启动流程总结
|
6天前
|
SQL XML Java
【JavaEE进阶】 MyBatis之动态SQL
【JavaEE进阶】 MyBatis之动态SQL
|
8天前
|
SQL Java 数据库连接
【极光系列】SpringBoot集成Mybatis
【极光系列】SpringBoot集成Mybatis
24 1
【极光系列】SpringBoot集成Mybatis
|
8天前
|
XML 监控 druid
【Java专题_02】springboot+mybatis+pagehelper分页插件+druid数据源详细教程
【Java专题_02】springboot+mybatis+pagehelper分页插件+druid数据源详细教程
32 0
|
9天前
|
存储 SQL 数据安全/隐私保护
Mybatis-Plus 拦截SQL语句实现加解密存储
Mybatis-Plus 拦截SQL语句实现加解密存储
17 0
|
27天前
|
缓存 Java uml
SpringBoot2 | Spring IOC 流程中核心扩展接口的12个扩展点源码分析(十一)
SpringBoot2 | Spring IOC 流程中核心扩展接口的12个扩展点源码分析(十一)
25 0
|
27天前
|
Java 容器 Spring
SpringBoot2 | @SpringBootApplication注解 自动化配置流程源码分析(三)
SpringBoot2 | @SpringBootApplication注解 自动化配置流程源码分析(三)
24 0
|
27天前
|
Java 中间件 容器
SpringBoot2 | SpringBoot启动流程源码分析(一)
SpringBoot2 | SpringBoot启动流程源码分析(一)
30 0

相关产品

  • 云迁移中心