欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Mybatis動(dòng)態(tài)元素if的使用方式

 更新時(shí)間:2023年12月01日 09:50:31   作者:三省同學(xué)  
這篇文章主要介紹了Mybatis動(dòng)態(tài)元素if的使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

問題

代碼

<if test="status != null and status != ''">
    AND status = #{status}
</if>

Mybatis動(dòng)態(tài)元素if使用,上面寫法適用于status類型為字符串。

若為整型,如int/Integer,當(dāng)status為0時(shí),就不會(huì)進(jìn)入判斷

解決

1:

<if test="status != null and status != '' or status == 0">
         AND u.status = #{status}
</if>

2

<if test="status != null">
         AND u.status = #{status}
</if>

源碼閱讀

查看SQL生成 

根據(jù)斷點(diǎn)進(jìn)入PageInterceptor

@Override
public Object intercept(Invocation invocation) throws Throwable {
    try {
        Object[] args = invocation.getArgs();
        MappedStatement ms = (MappedStatement) args[0];
        Object parameter = args[1];
        RowBounds rowBounds = (RowBounds) args[2];
        ResultHandler resultHandler = (ResultHandler) args[3];
        Executor executor = (Executor) invocation.getTarget();
        CacheKey cacheKey;
        BoundSql boundSql;
        //由于邏輯關(guān)系,只會(huì)進(jìn)入一次
        if (args.length == 4) {
            //4 個(gè)參數(shù)時(shí)
            boundSql = ms.getBoundSql(parameter);
            cacheKey = executor.createCacheKey(ms, parameter, rowBounds, boundSql);
        } else {
            //6 個(gè)參數(shù)時(shí)
            cacheKey = (CacheKey) args[4];
            boundSql = (BoundSql) args[5];
        }
        checkDialectExists();
        //對(duì) boundSql 的攔截處理
        if (dialect instanceof BoundSqlInterceptor.Chain) {
            boundSql = ((BoundSqlInterceptor.Chain) dialect).doBoundSql(BoundSqlInterceptor.Type.ORIGINAL, boundSql, cacheKey);
        }
        ...

進(jìn)入MappedStatement查看SQL動(dòng)態(tài)綁定

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

rootSqlNode.apply(context);這句代碼很關(guān)鍵查看IF元素最終執(zhí)行結(jié)果

@Override
public BoundSql getBoundSql(Object parameterObject) {
  DynamicContext context = new DynamicContext(configuration, parameterObject);
  rootSqlNode.apply(context);
  SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);
  Class<?> parameterType = parameterObject == null ? Object.class : parameterObject.getClass();
  SqlSource sqlSource = sqlSourceParser.parse(context.getSql(), parameterType, context.getBindings());
  BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
  for (Map.Entry<String, Object> entry : context.getBindings().entrySet()) {
    boundSql.setAdditionalParameter(entry.getKey(), entry.getValue());
  }
  return boundSql;
}

循環(huán)動(dòng)態(tài)元素節(jié)點(diǎn)

@Override
public boolean apply(DynamicContext context) {
  for (SqlNode sqlNode : contents) {
    sqlNode.apply(context);
  }
  return true;
}

在這里插入圖片描述

進(jìn)入類IfSqlNode

evaluator.evaluateBoolean(test, context.getBindings())如果為false就不會(huì)進(jìn)入元素判斷中

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

判斷邏輯

public class ExpressionEvaluator {

  public boolean evaluateBoolean(String expression, Object parameterObject) {
    Object value = OgnlCache.getValue(expression, parameterObject);
    if (value instanceof Boolean) {
      return (Boolean) value;
    }
    if (value instanceof Number) {
        return !new BigDecimal(String.valueOf(value)).equals(BigDecimal.ZERO);
    }
    return value != null;
  }
  ...

進(jìn)入類OgnlCache

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);
  }
}
protected Object evaluateGetValueBody(OgnlContext context, Object source) throws OgnlException {
     context.setCurrentObject(source);
     context.setCurrentNode(this);
     if (!this._constantValueCalculated) {
         this._constantValueCalculated = true;
         boolean constant = this.isConstant(context);
         if (constant) {
             this._constantValue = this.getValueBody(context, source);
         }

         this._hasConstantValue = constant;
     }

     return this._hasConstantValue ? this._constantValue : this.getValueBody(context, source);
 }
protected Object getValueBody(OgnlContext context, Object source) throws OgnlException {
    Object v1 = this._children[0].getValue(context, source);
    Object v2 = this._children[1].getValue(context, source);
    return OgnlOps.equal(v1, v2) ? Boolean.FALSE : Boolean.TRUE;
}
public static boolean equal(Object v1, Object v2) {
    if (v1 == null) {
        return v2 == null;
    } else if (v1 != v2 && !isEqual(v1, v2)) {
        if (v1 instanceof Number && v2 instanceof Number) {
            return ((Number)v1).doubleValue() == ((Number)v2).doubleValue();
        } else {
            return false;
        }
    } else {
        return true;
    }
}
public static boolean isEqual(Object object1, Object object2) {
    boolean result = false;
    if (object1 == object2) {
        result = true;
    } else if (object1 != null && object1.getClass().isArray()) {
        if (object2 != null && object2.getClass().isArray() && object2.getClass() == object1.getClass()) {
            result = Array.getLength(object1) == Array.getLength(object2);
            if (result) {
                int i = 0;

                for(int icount = Array.getLength(object1); result && i < icount; ++i) {
                    result = isEqual(Array.get(object1, i), Array.get(object2, i));
                }
            }
        }
    } else {
        result = object1 != null && object2 != null && (object1.equals(object2) || compareWithConversion(object1, object2) == 0);
    }

    return result;
}

關(guān)鍵代碼

public static int compareWithConversion(Object v1, Object v2) {
       int result;
       if (v1 == v2) {
           result = 0;
       } else {
           int t1 = getNumericType(v1);
           int t2 = getNumericType(v2);
           int type = getNumericType(t1, t2, true);
           switch(type) {
           case 6:
               result = bigIntValue(v1).compareTo(bigIntValue(v2));
               break;
           case 9:
               result = bigDecValue(v1).compareTo(bigDecValue(v2));
               break;
           case 10:
               if (t1 == 10 && t2 == 10) {
                   if (v1 instanceof Comparable && v1.getClass().isAssignableFrom(v2.getClass())) {
                       result = ((Comparable)v1).compareTo(v2);
                       break;
                   }

                   throw new IllegalArgumentException("invalid comparison: " + v1.getClass().getName() + " and " + v2.getClass().getName());
               }
           case 7:
           case 8:
               double dv1 = doubleValue(v1);
               double dv2 = doubleValue(v2);
               return dv1 == dv2 ? 0 : (dv1 < dv2 ? -1 : 1);
           default:
               long lv1 = longValue(v1);
               long lv2 = longValue(v2);
               return lv1 == lv2 ? 0 : (lv1 < lv2 ? -1 : 1);
           }
       }

       return result;
   }
public static double doubleValue(Object value) throws NumberFormatException {
   if (value == null) {
       return 0.0D;
   } else {
       Class c = value.getClass();
       if (c.getSuperclass() == Number.class) {
           return ((Number)value).doubleValue();
       } else if (c == Boolean.class) {
           return (Boolean)value ? 1.0D : 0.0D;
       } else if (c == Character.class) {
           return (double)(Character)value;
       } else {
       		// 原因就這了?。?!
           String s = stringValue(value, true);
           return s.length() == 0 ? 0.0D : Double.parseDouble(s);
       }
   }
}

為什么為0時(shí),進(jìn)不去

結(jié)論:

從斷點(diǎn)跟進(jìn)源碼得出,當(dāng)!=null條件是,Mybatis會(huì)把傳進(jìn)去的值與null比較,0.0==null為false,當(dāng)比較空字符""時(shí),會(huì)先把空字符進(jìn)行一次轉(zhuǎn)化doubleValue(v2),結(jié)果為0.0。

所以當(dāng)status是整型且為0時(shí),就不會(huì)進(jìn)入判斷

重要源碼節(jié)點(diǎn)

SimpleNode::getValue—>SimpleNode::evaluateGetValueBody—>ASTEq::getValueBody—>OgnlOps::equal—>OgnlOps::compareWithConversion

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Android圖片轉(zhuǎn)換器代碼分享

    Android圖片轉(zhuǎn)換器代碼分享

    本文給大家總結(jié)了下在安卓程序中進(jìn)行圖片轉(zhuǎn)換的方法,非常的實(shí)用,小伙伴們可以參考下。
    2015-10-10
  • Java使用itextpdf實(shí)現(xiàn)Excel轉(zhuǎn)PDF

    Java使用itextpdf實(shí)現(xiàn)Excel轉(zhuǎn)PDF

    這篇文章主要為大家詳細(xì)介紹了Java如何使用itextpdf實(shí)現(xiàn)Excel轉(zhuǎn)PDF,并且支持xlsx和xls兩種格,文中的示例代碼講解詳細(xì),希望對(duì)大家有所幫助
    2024-01-01
  • Springboot jdbctemplate整合實(shí)現(xiàn)步驟解析

    Springboot jdbctemplate整合實(shí)現(xiàn)步驟解析

    這篇文章主要介紹了Springboot jdbctemplate整合實(shí)現(xiàn)步驟解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-08-08
  • SpringBoot集成極光推送完整實(shí)現(xiàn)代碼

    SpringBoot集成極光推送完整實(shí)現(xiàn)代碼

    本文主要介紹了SpringBoot集成極光推送完整實(shí)現(xiàn)代碼,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • Java中使用JavaMail多發(fā)郵件及郵件的驗(yàn)證和附件實(shí)現(xiàn)

    Java中使用JavaMail多發(fā)郵件及郵件的驗(yàn)證和附件實(shí)現(xiàn)

    這篇文章主要介紹了Java中使用Java Mail多發(fā)郵件及郵件的驗(yàn)證和附件實(shí)現(xiàn),包括在郵件中加入圖片等功能的實(shí)現(xiàn)講解,需要的朋友可以參考下
    2016-02-02
  • 詳解如何使用maven生成可以執(zhí)行的jar

    詳解如何使用maven生成可以執(zhí)行的jar

    這篇文章主要介紹了詳解如何使用maven生成可以執(zhí)行的jar,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-06-06
  • JDBC獲取數(shù)據(jù)庫連接的5種方式實(shí)例

    JDBC獲取數(shù)據(jù)庫連接的5種方式實(shí)例

    JDBC是一種用于執(zhí)行SQL語句的JavaAPI,為多種關(guān)系數(shù)據(jù)庫提供統(tǒng)一訪問,它由一組用Java語言編寫的類和接口組成,提供了諸如查詢和更新數(shù)據(jù)庫中數(shù)據(jù)的方法,這篇文章主要給大家介紹了關(guān)于JDBC獲取數(shù)據(jù)庫連接的5種方式,需要的朋友可以參考下
    2022-06-06
  • 詳解Spring注解--@Autowired、@Resource和@Service

    詳解Spring注解--@Autowired、@Resource和@Service

    本篇文章主要介紹最重要的三個(gè)Spring注解,也就是@Autowired、@Resource和@Service,具有很好的參考價(jià)值。下面跟著小編一起來看下吧
    2017-05-05
  • java同一個(gè)類中,一個(gè)無事務(wù)方法調(diào)用一個(gè)有事務(wù)方法時(shí),事務(wù)失效問題

    java同一個(gè)類中,一個(gè)無事務(wù)方法調(diào)用一個(gè)有事務(wù)方法時(shí),事務(wù)失效問題

    本文詳細(xì)介紹了Spring框架中事務(wù)管理的實(shí)現(xiàn)原理,包括@Transactional注解的使用、事務(wù)的開啟、提交和回滾機(jī)制,以及代理對(duì)象的兩種實(shí)現(xiàn)方式(JDK動(dòng)態(tài)代理和CGLIB代理),文章還探討了在同一個(gè)類中調(diào)用有事務(wù)方法時(shí)事務(wù)失效的原因,并提供了解決方法
    2024-12-12
  • Spring中bean集合注入的方法詳解

    Spring中bean集合注入的方法詳解

    Spring作為項(xiàng)目中不可缺少的底層框架,提供的最基礎(chǔ)的功能就是bean的管理了。bean的注入相信大家都比較熟悉了,但是有幾種不太常用到的集合注入方式,可能有的同學(xué)會(huì)不太了解,今天我們就通過實(shí)例看看它的使用
    2022-07-07

最新評(píng)論