执行增删改查时获取SQL语句

这篇具有很好参考价值的文章主要介绍了执行增删改查时获取SQL语句。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

mapper.xml中的sql会在MybatisAutoConfiguration中构建SqlSessionFactory时得到解析,如果有where if之类的标签会被解析成DynamicSqlSource,如果是普通的查询语句(select * from departments where department_id=#{depId})则会被解析成RawSqlSource,这个属性会被存在configuration的mappedstatements属性中,属性名称为sqlSource。然后执行查询时,会从sqlSource中拿到对应的原始sql,然后再进行解析,得到完整的sql。方法就是对应的SqlSource类的getBoundsql方法。

查询为例
查询方法由SqlSessionTemplate中创建DefaultSqlSession,然后执行DefaultSqlSession的selectList方法。
执行增删改查时获取SQL语句
执行增删改查时获取SQL语句
执行增删改查时获取SQL语句
然后继续执行查询方法
执行executor.query方法,executor为CachingExecutor类型。

执行增删改查时获取SQL语句

如果引入了pagehelper依赖,这里执行前会进入分页拦截器
执行增删改查时获取SQL语句
关键方法是这个getBoundsql,就是通过这个方法获取到sql的。
执行增删改查时获取SQL语句
BoundSql

public class BoundSql {
    // 一个完整的 SQL 语句,可能会包含问号 ? 占位符
    private final String sql;
    // 参数映射列表,SQL 中的每个 #{xxx} 占位符都会被解析成相应的 ParameterMapping 对象
    private final List<ParameterMapping> parameterMappings;
    // 运行时参数,即用户传入的参数,比如 Article 对象,或是其他的参数
    private final Object parameterObject;
    // 附加参数集合,用于存储一些额外的信息,比如 datebaseId 等
    private final Map<String, Object> additionalParameters;
    // additionalParameters 的元信息对象
    private final MetaObject metaParameters;
}

getBoundSql方法

  public BoundSql getBoundSql(Object parameterObject) {
  	//获取BoundSql 
    BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
    //获取参数映射
    List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
    if (parameterMappings == null || parameterMappings.isEmpty()) {
      boundSql = new BoundSql(configuration, boundSql.getSql(), parameterMap.getParameterMappings(), parameterObject);
    }

    // check for nested result maps in parameter mappings (issue #30)
    for (ParameterMapping pm : boundSql.getParameterMappings()) {
      String rmId = pm.getResultMapId();
      if (rmId != null) {
        ResultMap rm = configuration.getResultMap(rmId);
        if (rm != null) {
          hasNestedResultMaps |= rm.hasNestedResultMaps();
        }
      }
    }

    return boundSql;
  }

1.动态解析

这里如果参数是${}这样的,就会走DynamicSqlSource类的getBoundSql
执行增删改查时获取SQL语句
然后执行MixedSqlNode类apply方法把 ${}的内容替换成真实数据
传入的是原始sql
执行增删改查时获取SQL语句
TextSqlNode类的apply方法
执行增删改查时获取SQL语句
GenericTokenParser类的parse方法
执行增删改查时获取SQL语句
关键方法
执行增删改查时获取SQL语句
TextSqlNode类的handleToken方法
从context拿到值,根据传进来的key
执行增删改查时获取SQL语句
这时拿到的sql就是完整的sql了
执行增删改查时获取SQL语句
解析if where 动态标签
DynamicSqlSource类的getBoundSql方法

  public BoundSql getBoundSql(Object parameterObject) {
    DynamicContext context = new DynamicContext(configuration, parameterObject);
    //拿到原始sql 解析if标签 如果判断正确 会拼装if标签下的sql 解析${} 但不会解析#{}
    rootSqlNode.apply(context);
    
    SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);
    Class<?> parameterType = parameterObject == null ? Object.class : parameterObject.getClass();
    //调用SqlSourceBuilder的parse方法 解析#{}变成? 这和一开始解析mapper中普通sql时的#{}是相同的方法
    SqlSource sqlSource = sqlSourceParser.parse(context.getSql(), parameterType, context.getBindings());
    //拿到BoundSql 并返回 这时只有#{}中的内容还是?后面要处理
    BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
    context.getBindings().forEach(boundSql::setAdditionalParameter);
    return boundSql;
  }

拿到sql继续执行查询操作

关键方法
rootSqlNode.apply(context)
执行增删改查时获取SQL语句

2.静态解析

如果是#{}
则会走StaticSqlSource类的getBoundSql方法
执行增删改查时获取SQL语句
执行完参数还是 问号?
执行增删改查时获取SQL语句
然后继续执行查询方法,应该是在最终查询时将实际数据传入的。
继续CachingExecutor的query方法
执行增删改查时获取SQL语句
然后执行BaseExecutor类的query方法
没有缓存的话去数据库查询

执行增删改查时获取SQL语句
继续BaseExecutor类的queryFromDatabase方法
先把key放入缓存,然后继续执行doQuery方法

执行增删改查时获取SQL语句
SimpleExecutor类的doQuery方法
执行增删改查时获取SQL语句
关键方法 prepareStatement() 方法
SimpleExecutor类的prepareStatement方法
执行增删改查时获取SQL语句
关键方法parameterize
就是这个方法给 ?赋的值
RoutingStatementHandler类的parameterize方法
执行增删改查时获取SQL语句
DefaultParameterHandler类的setParameters方法

  public void setParameters(PreparedStatement ps) {
    ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
    //从boundSql拿到参数的标识
    List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
    if (parameterMappings != null) {
      for (int i = 0; i < parameterMappings.size(); i++) {
        ParameterMapping parameterMapping = parameterMappings.get(i);
        if (parameterMapping.getMode() != ParameterMode.OUT) {
          Object value;
          //拿到属性名
          String propertyName = parameterMapping.getProperty();
          if (boundSql.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional params
            value = boundSql.getAdditionalParameter(propertyName);
          } else if (parameterObject == null) {
            value = null;
          } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
            value = parameterObject;
          } else {
          	//parameterObject就是传入的值
            MetaObject metaObject = configuration.newMetaObject(parameterObject);
            //根据key拿到value 这样就拿到了我们传入的值
            value = metaObject.getValue(propertyName);
          }
          TypeHandler typeHandler = parameterMapping.getTypeHandler();
          JdbcType jdbcType = parameterMapping.getJdbcType();
          if (value == null && jdbcType == null) {
            jdbcType = configuration.getJdbcTypeForNull();
          }
          try {
            // 由类型处理器 typeHandler 向 ParameterHandler 设置参数
            typeHandler.setParameter(ps, i + 1, value, jdbcType);
          } catch (TypeException | SQLException e) {
            throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
          }
        }
      }
    }
  }

值不是拼到sql 而是保存在columnMap中,,也就是不拼接sql,而是采用传参的方式。
执行增删改查时获取SQL语句

至此,${} 和#{}的赋值就完成了,还需要分析的是《where》这种标签是怎么解析的,最后就是执行最终的查询了。
执行增删改查时获取SQL语句
todo 查询后对结果进行解析文章来源地址https://www.toymoban.com/news/detail-429051.html

到了这里,关于执行增删改查时获取SQL语句的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • hibernate5 根据xml获取ddl sql语句

    根据以上查看源码后,发现实现可以这样写 仅改一改参数就可以迁移hibernate6

    2024年04月27日
    浏览(20)
  • sql中的时间范围查询【三种方式】以及Mapper.xml中遇到大于号小于号问题解决方案

    mapper注意事项 字符 转义字符 描述 gt; 大于 = gt;= 大于等于 lt; 小于 = lt;= 小于等于 \\\" quot; 双引号 ’ apos; 单引号 amp; and 遇到问题: 从数据库获取时间传到前端进行展示的时候,我们有时候可能无法得到一个满意的时间格式的时间日期,在数据库中显示的是正确的时间格式,获

    2024年02月10日
    浏览(34)
  • MyBatis XML 映射文件中的 SQL 语句可以分为动态语句和静态语句

    目录 静态查询: 动态查询: 静态更新: 动态更新: 静态删除: 动态删除: 动态语句和静态语句在 MyBatis 中的作用如下: 静态查询: 静态查询是指在 SQL 语句中执行固定的查询操作,查询的条件和内容是预先确定的,不会随着用户输入或其他条件的改变而改变。以下是一

    2024年01月18日
    浏览(52)
  • Idea设置Mapper.xml文件中SQL命令格式化

    目录 一、遇到问题 二、解决方法 一、遇到问题  使用Idea给项目的Mapper.xml文件配置sql语句时,发现在Mapper.xml文件里粘贴SQL命令时,Mapper.xml文件中使用 Alt+Shift+L 没有 格式化 成功  粘贴代码(不能自动缩进) 之前也在pom文件中解决了xml没有自动缩进格式化的问题,但是对S

    2024年02月15日
    浏览(39)
  • mybatis中的mapper.xml中如何使用in方法

    提示:mapper.xml中如何使用in方法一般都是like或= 提示:使用foreach 注意,传入的参数是List ,如果传入的是array 则需要修改 collection部分定义为 collection=“array” 在MyBatis中使用in参数为集合时,需要使用到foreach标签。 下面详细介绍以下foreach标签的几个参数

    2024年02月15日
    浏览(33)
  • idea写sql语句快捷键提醒,mapper注解开发,mybatis

    第一步:注入SQL语言 1.显示上下文操作(没有这个选项的话就选中sql然后直接alt+回车快捷键) 2.注入语言或引用 3.mysql 第二步:配置MySQL数据库连接 1.首先点击侧边的数据库,再点击上面的加号 2.点击数据源,然后找到MySQL并点击 3.配置数据库信息(填写账号密码后点击测试

    2024年01月16日
    浏览(35)
  • 【SQL基础】SQL增删改查基本语句

    增删改查是一个数据操作工具最基本的命令,在SQL中,这四种语句主要由以下语句执行: 增:insert 删:delete 改:update 查:select 功能:SELECT 语句用于从数据库中选取数据。 结果:选取结果被存储在一个结果表中,称为结果集。 语法:可以用以下语句选择特定列名,

    2023年04月08日
    浏览(26)
  • 【问题记录】IDEA Mybatis *Mapper.xml 中 sql 无提示、无高亮、格式化失效问题 (已解决)

    【 问题 】 先说版本,win 11,idea 2023.1 如标题,想去格式化mybatis中写的sql,但是ctrl alt L 一顿处理,其中的sql没有按照sql命令的格式去格式化,此外写sql 无提示也无高亮 【 问题示例 】 未格式化前,显然格式已经差不多了,按理来说再格式化也就稍微调整 但格式化的结果是

    2024年02月04日
    浏览(37)
  • 面试之快速学习SQL-基础增删改查语句

    在表中,可能会包含重复值。这并不成问题,不过,有时您也许希望仅仅列出不同(distinct)的值。 操作符 描述 引号的使用 请注意 , 我们在例子中的条件值周围使用的是单引号 。 SQL 使用单引号来环绕文本值(大部分数据库系统也接受双引号)。如果是数值,请不要使用

    2024年02月14日
    浏览(24)
  • 常见关系型数据库SQL增删改查语句

    常见关系型数据库SQL增删改查语句: 创建表(Create Table): 插入数据(Insert Into): 查询数据(Select): 更新数据(Update): 删除数据(Delete): 联结(Join): 子查询(Subquery): 排序(Order By): 分组(Group By): 使用子查询、排序和分组的常见SQL操作。可以根据具体

    2024年02月09日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包