首頁 > 軟體

Mybatis的動態Sql組合模式詳情

2022-08-18 14:00:24

前言

當同一型別的很多物件組成一個樹結構的時候,可以考慮使用組合模式,組合模式涉及三個類:

Component介面:定義樹的各個節點的一些操作

Left類:這個是樹的葉子結點,實現Component介面,對於節點的管理它不去實現,只實現業務邏輯

Composite類:這個是樹的非葉子節點,實現Component介面,不但實現業務邏輯,同時會管理子節點,會有個Component介面的集合類來管理子節點

Component角色

SqlNode就是扮演組合模式中的Component角色,Sql標籤會解析成SqlNode物件,

public interface SqlNode {
  boolean apply(DynamicContext context);
}

Composite角色

MixedSqlNode類扮演組合模式的Composite角色:

它也是解析<otherwise>標籤的類

public class MixedSqlNode implements SqlNode {
  private final List<SqlNode> contents;

  public MixedSqlNode(List<SqlNode> contents) {
    this.contents = contents;
  }

  @Override
  public boolean apply(DynamicContext context) {
    contents.forEach(node -> node.apply(context));
    return true;
  }
}

它有個SqlNode的集合類,記錄SqlNode物件,apply方法就是遍歷集合,依次呼叫自己的apply()方法

剩餘其他SqlNode的實現類就充當組合模式的Left類了:

Left類角色

TextSqlNode

TextSqlNode是包含${}的動態sql片段,它的apply()方法的實現:

  @Override
  public boolean apply(DynamicContext context) {
    GenericTokenParser parser = createParser(new BindingTokenParser(context, injectionFilter));
    context.appendSql(parser.parse(text));
    return true;
  }
  private GenericTokenParser createParser(TokenHandler handler) {
    return new GenericTokenParser("${", "}", handler);
  }

建立GenericTokenParser解析器,然後解析包含${}的sql片段,解析後儲存到DynamicContext中

TrimSqlNode

TrimSqlNode是解析出的trim標籤的物件,trim標籤可以去除sql的and、逗號或者拼接where關鍵字等,

  private final SqlNode contents;
  @Override
  public boolean apply(DynamicContext context) {
    FilteredDynamicContext filteredDynamicContext = new FilteredDynamicContext(context);
    boolean result = contents.apply(filteredDynamicContext);
    filteredDynamicContext.applyAll();
    return result;
  }

先呼叫SqlNode 的apply方法 ,然後呼叫FilteredDynamicContext的applyAll()方法進行前字尾的處理,FilteredDynamicContext在DynamicContext包裝了一層,利用了裝飾者模式,除了DynamicContext的儲存解析結果和引數功能外還能進行前字尾的處理

IfSqlNode

IfSqlNode是解析出if 標籤、when標籤的類,

public class IfSqlNode implements SqlNode {
  private final ExpressionEvaluator evaluator;
  private final String test;
  private final SqlNode contents;

  public IfSqlNode(SqlNode contents, String test) {
    this.test = test;
    this.contents = contents;
    this.evaluator = new ExpressionEvaluator();
  }

  @Override
  public boolean apply(DynamicContext context) {
    if (evaluator.evaluateBoolean(test, context.getBindings())) {
      contents.apply(context);
      return true;
    }
    return false;
  }
}

ExpressionEvaluator是解析工具類,test記錄了if標籤的test表示式,apply()方法中ExpressionEvaluator工具類解析test表示式,返回true之後呼叫具體SqlNode的apply()方法

StaticTextSqlNode

StaticTextSqlNode是非動態的sql片段,apply()方法直接把sql片段追加到DynamicContext的sqlBuilder屬性中

public class StaticTextSqlNode implements SqlNode {
  private final String text;

  public StaticTextSqlNode(String text) {
    this.text = text;
  }

  @Override
  public boolean apply(DynamicContext context) {
    context.appendSql(text);
    return true;
  }
}

總結

這篇文章從組合模式的角度分析了Mybatis動態sql的部分,SqlNode是組合模式的Component介面,MixedSqlNode是組合模式的Composite角色,還有其他的SqlNode的實現類TextSqlNode、TrimSqlNode、IfSqlNode、StaticTextSqlNode,它們是解析不同的標籤,TextSqlNode解析包含${}的動態sql片段,TrimSqlNode類解析trim標籤,IfSqlNode是解析出if 標籤、when標籤的類,StaticTextSqlNode是非動態的sql片段

到此這篇關於Mybatis的動態Sql組合模式詳情的文章就介紹到這了,更多相關Mybatis 組合模式內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com