您现在的位置是:首页 >其他 >执行增删改查时获取SQL语句网站首页其他

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

执迷11 2023-06-22 08:00:02
简介执行增删改查时获取SQL语句

查询为例
查询方法由SqlSessionTemplate中创建DefaultSqlSession,然后执行DefaultSqlSession的selectList方法。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
然后继续执行查询方法
执行executor.query方法,executor为CachingExecutor类型。

在这里插入图片描述

如果引入了pagehelper依赖,这里执行前会进入分页拦截器
在这里插入图片描述
关键方法是这个getBoundsql,就是通过这个方法获取到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;
  }

这里如果参数是${}这样的,就会走DynamicSqlSource类的getBoundSql
在这里插入图片描述
然后执行MixedSqlNode类apply方法把 ${}的内容替换成真实数据
传入的是原始sql
在这里插入图片描述
TextSqlNode类的apply方法
在这里插入图片描述
GenericTokenParser类的parse方法
在这里插入图片描述
关键方法
在这里插入图片描述
TextSqlNode类的handleToken方法
从context拿到值,根据传进来的key
在这里插入图片描述
这时拿到的sql就是完整的sql了
在这里插入图片描述

如果是#{}
则会走StaticSqlSource类的getBoundSql方法
在这里插入图片描述
执行完参数还是 问号?
在这里插入图片描述
然后继续执行查询方法,应该是在最终查询时将实际数据传入的。
继续CachingExecutor的query方法
在这里插入图片描述
然后执行BaseExecutor类的query方法
没有缓存的话去数据库查询

在这里插入图片描述
继续BaseExecutor类的queryFromDatabase方法
先把key放入缓存,然后继续执行doQuery方法

在这里插入图片描述
SimpleExecutor类的doQuery方法
在这里插入图片描述
关键方法 prepareStatement() 方法
SimpleExecutor类的prepareStatement方法
在这里插入图片描述
关键方法parameterize
就是这个方法给 ?赋的值
RoutingStatementHandler类的parameterize方法
在这里插入图片描述
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);
          }
        }
      }
    }
  }

至此,${} 和#{}的赋值就完成了,还需要分析的是《where》这种标签是怎么解析的,最后就是执行最终的查询了。
在这里插入图片描述
todo 查询后对结果进行解析

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。