3

mybatis系列-sql 类的简要分析

 1 year ago
source link: https://nicksxs.me/2023/03/19/mybatis%E7%B3%BB%E5%88%97-sql-%E7%B1%BB%E7%9A%84%E7%AE%80%E8%A6%81%E5%88%86%E6%9E%90/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

mybatis系列-sql 类的简要分析

上次就比较简单的讲了使用,这块也比较简单,因为封装得不是很复杂,首先我们从 select 作为入口来看看,这个具体的实现,

String selectSql = new SQL() {{
            SELECT("id", "name");
            FROM("student");
            WHERE("id = #{id}");
        }}.toString();

SELECT 方法的实现,

public T SELECT(String... columns) {
  sql().statementType = SQLStatement.StatementType.SELECT;
  sql().select.addAll(Arrays.asList(columns));
  return getSelf();
}

statementType是个枚举

public enum StatementType {
  DELETE, INSERT, SELECT, UPDATE
}

那这个就是个 select 语句,然后会把参数转成 list 添加到 select 变量里,
然后是 from 语句,这个大概也能猜到就是设置下表名,

public T FROM(String table) {
  sql().tables.add(table);
  return getSelf();
}

往 tables 里添加了 table,这个 tables 是什么呢
这里也可以看下所有的变量,

StatementType statementType;
List<String> sets = new ArrayList<>();
List<String> select = new ArrayList<>();
List<String> tables = new ArrayList<>();
List<String> join = new ArrayList<>();
List<String> innerJoin = new ArrayList<>();
List<String> outerJoin = new ArrayList<>();
List<String> leftOuterJoin = new ArrayList<>();
List<String> rightOuterJoin = new ArrayList<>();
List<String> where = new ArrayList<>();
List<String> having = new ArrayList<>();
List<String> groupBy = new ArrayList<>();
List<String> orderBy = new ArrayList<>();
List<String> lastList = new ArrayList<>();
List<String> columns = new ArrayList<>();
List<List<String>> valuesList = new ArrayList<>();

可以看到是一堆 List 先暂存这些sql 片段,然后再拼装成 sql 语句,
因为它重写了 toString 方法

@Override
public String toString() {
  StringBuilder sb = new StringBuilder();
  sql().sql(sb);
  return sb.toString();
}

调用的 sql 方法是

public String sql(Appendable a) {
      SafeAppendable builder = new SafeAppendable(a);
      if (statementType == null) {
        return null;
      }

      String answer;

      switch (statementType) {
        case DELETE:
          answer = deleteSQL(builder);
          break;

        case INSERT:
          answer = insertSQL(builder);
          break;

        case SELECT:
          answer = selectSQL(builder);
          break;

        case UPDATE:
          answer = updateSQL(builder);
          break;

        default:
          answer = null;
      }

      return answer;
    }

根据上面的 statementType判断是个什么 sql,我们这个是 selectSQL 就走的 SELECT 这个分支

private String selectSQL(SafeAppendable builder) {
  if (distinct) {
    sqlClause(builder, "SELECT DISTINCT", select, "", "", ", ");
  } else {
    sqlClause(builder, "SELECT", select, "", "", ", ");
  }

  sqlClause(builder, "FROM", tables, "", "", ", ");
  joins(builder);
  sqlClause(builder, "WHERE", where, "(", ")", " AND ");
  sqlClause(builder, "GROUP BY", groupBy, "", "", ", ");
  sqlClause(builder, "HAVING", having, "(", ")", " AND ");
  sqlClause(builder, "ORDER BY", orderBy, "", "", ", ");
  limitingRowsStrategy.appendClause(builder, offset, limit);
  return builder.toString();
}

上面的可以看出来就是按我们常规的 sql 理解顺序来处理
就是select ... from ... where ...这样子
再看下 sqlClause 的代码

private void sqlClause(SafeAppendable builder, String keyword, List<String> parts, String open, String close,
                           String conjunction) {
      if (!parts.isEmpty()) {
        if (!builder.isEmpty()) {
          builder.append("\n");
        }
        builder.append(keyword);
        builder.append(" ");
        builder.append(open);
        String last = "________";
        for (int i = 0, n = parts.size(); i < n; i++) {
          String part = parts.get(i);
          if (i > 0 && !part.equals(AND) && !part.equals(OR) && !last.equals(AND) && !last.equals(OR)) {
            builder.append(conjunction);
          }
          builder.append(part);
          last = part;
        }
        builder.append(close);
      }
    }

这里的拼接方式还需要判断 AND 和 OR 的判断逻辑,其他就没什么特别的了,只是where 语句中的 lastList 不知道是干嘛的,好像只有添加跟赋值的操作,有知道的大神也可以评论指导下


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK