Mybatis if-Label-Parameterüberprüfungslogik vom Typ „Nicht-String“.

Lassen Sie uns ohne weitere Umschweife über die Nutzung sprechen

Nach dem Entfernen von Objekten vom Typ String in Java können die verbleibenden Objekttypen grob in die folgenden drei Kategorien eingeteilt werden:

  • Grundlegende numerische Typen (int, long, float, double usw.)
  • Boolescher Typ (boolean)
  • Andere Typen (einschließlich grundlegender Typ-Wrapper-Klassen, benutzerdefinierter Typen)

Für den ersten Typ des grundlegenden Zahlentyps können Operatoren wie „größer als“, „kleiner als“ und „gleich“ im if-Tag von Mybatis zur bedingten Beurteilung verwendet werden. Zum Beispiel:

<!-- 示例:根据 age 参数生成动态 SQL -->
<select id="getUserByAge" parameterType="int" resultType="com.example.User">
  SELECT * FROM user
  WHERE 
    <if test="age != null and age gt 0">
      age = #{age}
    </if>
</select>

Hinweis: Der Ausdruck im <if>-Tag basiert auf OGNL und der Vergleichsoperator in OGNL ist lt, was kleiner als für kleiner als und größer als verwenden. Und wenn es als leer beurteilt wird, kann direkt beurteilt werden, dass es nicht gleich Null ist. und -Tags verwenden, sollten Sie daher gt bedeutet größer als. Wenn Sie OGNL-Ausdrücke in <if>ltgt

Für den zweiten booleschen Typ können Sie true und false direkt für die bedingte Beurteilung verwenden, zum Beispiel:

<!-- 示例:根据 isVip 参数生成动态 SQL -->
<select id="getVipUsers" parameterType="boolean" resultType="com.example.User">
  SELECT * FROM user
  WHERE 
    <if test="isVip">
      is_vip = 1
    </if>
</select>

Hinweis: Der ognl-Ausdruck des obigen Tests kann zur Beurteilung auch als isVip==true geschrieben werden.

Für andere Typen der dritten Kategorie kann eine bedingte Beurteilung anhand der Eigenschaften oder Methoden von Java-Objekten erfolgen, zum Beispiel:

<!-- 示例:根据 User 对象的 gender 属性生成动态 SQL -->
<select id="getUserByGender" parameterType="com.example.User" resultType="com.example.User">
  SELECT * FROM user
  WHERE 
    <if test="gender != null and gender.equals('male')">
      gender = 'male'
    </if>
</select>

Hinweis: Der ognl-Ausdruck kann die Java-Objektmethode im Ausdruck analysieren und verwenden. Zum Beispiel: komplexe Objekte wie Sammlungsobjekte und Hash-Objekte. Für nicht statische Methoden in Objekten können Sie diese direkt verwenden, wie zum Beispiel: collection.size(). Wenn es sich um eine statische Methode, ein statisches Attribut oder eine benutzerdefinierte Toolklassenmethode handelt, muss sie aufgerufen werden@vollständiger Pfadklassenname@Eigenschaft/Methodenname< /span> >

===========================Höfliche Trennlinie==================== =================

Bei den oben genannten handelt es sich ausschließlich um spezifische Verwendungen. Im Folgenden finden Sie einige Regeln dafür, wie Mybatis OGNL-Ausdrücke (Object-Graph Navigation Language) analysiert.

Zunächst können Freunde über diese Website einen Blick auf den MyBatis-Quellcode mit chinesischen Kommentaren werfen:GitHub - tuguangquan/mybatis: Chinesische Kommentare zum Mybatis-Quellcode

 Da wir die Verarbeitungslogik des if-Knotens untersuchen, wenden wir uns direkt an

IfSqlNode-Codedatei unten:

/*
 *    Copyright 2009-2012 the original author or authors.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package org.apache.ibatis.scripting.xmltags;

/**
 * @author Clinton Begin
 */
/**
 * if SQL节点
 *
 */
public class IfSqlNode implements SqlNode {
  private ExpressionEvaluator evaluator;
  private String test;
  private SqlNode contents;

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

  @Override
  public boolean apply(DynamicContext context) {
    //如果满足条件,则apply,并返回true
    if (evaluator.evaluateBoolean(test, context.getBindings())) {
      contents.apply(context);
      return true;
    }
    return false;
  }

}

Es kann festgestellt werden, dass der Knoten nach der Instanziierung des if-Knotens durch Aufrufen der apply-Methode verarbeitet werden kann. Diese Methode ist in jeder Knotencodedatei vorhanden, und der if-Knoten implementiert die Beurteilung des Ausdrucks im Knoten durch Aufrufen von evaluator.evaluateBoolean.

  • Werfen wir einen Blick darauf, wie evaluator.evaluateBoolean Urteile fällt
  //表达式求布尔值,比如username == 'cbegin'
  public boolean evaluateBoolean(String expression, Object parameterObject) {
	//非常简单,就是调用ognl
    Object value = OgnlCache.getValue(expression, parameterObject);
    if (value instanceof Boolean) {
      //如果是Boolean
      return (Boolean) value;
    }
    if (value instanceof Number) {
        //如果是Number,判断不为0
        return !new BigDecimal(String.valueOf(value)).equals(BigDecimal.ZERO);
    }
    //否则判断不为null
    return value != null;
  }

Aus dem Code können wir erkennen, dass OgnlCache.getValue verwendet wird, um den Typ des Rückgabewerts zu bestimmen und das boolesche Ergebnis zu bestimmen.

  • Die OgnlCache.getValue-Logik ruft Ognl-Ausdrücke auf, um Knotenausdrücke zu analysieren, und Cache wird verwendet, um Ognl-Leistungsprobleme zu vermeiden.
// 缓存
private static final Map<String, Object> expressionCache = new ConcurrentHashMap<String, Object>();

public static Object getValue(String expression, Object root) {
    try {
      Map<Object, OgnlClassResolver> context = Ognl.createDefaultContext(root, new OgnlClassResolver());
      return Ognl.getValue(parseExpression(expression), context, root);
    } catch (OgnlException e) {
      throw new BuilderException("Error evaluating expression '" + expression + "'. Cause: " + e, e);
    }
  }

private static Object parseExpression(String expression) throws OgnlException {
    Object node = expressionCache.get(expression);
    if (node == null) {
      //大致意思就是OgnlParser.topLevelExpression很慢,所以加个缓存,放到ConcurrentHashMap里面
      node = Ognl.parseExpression(expression);
      expressionCache.put(expression, node);
    }
    return node;
  }
  • Ognl Jar-Paket-Quellcode und schließlich den ermittelten Wert des Ausdrucks durch kontinuierliche Iteration des Knotenknotens erhalten
// 创建默认上下文
public static Map createDefaultContext(Object root, ClassResolver classResolver) {
    return addDefaultContext(root, null, classResolver, null, new OgnlContext(classResolver, null, null));
}

// 增加默认上下文
public static Map addDefaultContext(Object root, MemberAccess memberAccess, ClassResolver classResolver, TypeConverter converter, Map context) {
    OgnlContext result;
    if (context instanceof OgnlContext) {
      result = (OgnlContext)context;
    } else {
      result = new OgnlContext(memberAccess, classResolver, converter, context);
    } 
    result.setRoot(root);
    return result;
}

// 获取Ognl值
public static Object getValue(Object tree, Map context, Object root) throws OgnlException {
    return getValue(tree, context, root, (Class)null);
}
  
// 实际逻辑
public static Object getValue(Object tree, Map context, Object root, Class resultType) throws OgnlException {
    Object result;
    OgnlContext ognlContext = (OgnlContext)addDefaultContext(root, context);
    Node node = (Node)tree;
    if (node.getAccessor() != null) {
      result = node.getAccessor().get(ognlContext, root);
    } else {
      result = node.getValue(ognlContext, root);
    } 
    if (resultType != null)
      result = getTypeConverter(context).convertValue(context, root, null, null, result, resultType); 
    return result;
}

Aus der obigen Logikkette können wir wahrscheinlich abstrahieren, wie Mybatis Ongl-Ausdrücke verwendet, um den if-Tag-Ausdruck zu beurteilen.

 

おすすめ

転載: blog.csdn.net/weixin_42505381/article/details/130029769