程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> 記錄一次bug解決過程:mybatis中$和#的使用,

記錄一次bug解決過程:mybatis中$和#的使用,

編輯:JAVA綜合教程

記錄一次bug解決過程:mybatis中$和#的使用,


一、總結

  mybatis中使用sqlMap進行sql查詢時,經常需要動態傳遞參數。動態SQL是mybatis的強大特性之一,也是它優於其他ORM框架的一個重要原因。mybatis在對sql語句進行預編譯之前,會對sql進行動態解析,解析為一個BoundSql對象,也是在此處對動態SQL進行處理的。在動態 SQL 解析階段,#{ }和${ }會有不同的表現,#{ }解析為一個JDBC預編譯語句(prepared statement)的參數標記符。

  一個 #{ } 被解析為一個參數占位符 ? 。${ } 僅僅為一個純碎的 string 替換,在動態 SQL 解析階段將會進行變量替換。

二、Bug描述

前端傳入參數:

skip:0
take:10
ruleName:A,B,C

業務層處理:

package SQL;

/**
 * 將前端多選參數轉義為SQL語句內容
 */
public class SQLUtil {

    private final static String REPLACECHAR_COMMA     = ",";
    private final static String REPLACECHAR_SEMICOLON = ";";

    public static void main(String[] args) {
        String s1 = "A,B,C";
        String s2 = "A B C";
        System.out.println("逗號分隔:" + formatInStr(s1));
        System.out.println("空格分隔:" + formatInStr(s2));
    }

    private static String formatInStr(String queryStr) {
        return queryInStr(sliptQueryStr(queryStr));
    }

    private static String[] sliptQueryStr(String queryStr) {
        if (null == queryStr || "".equals(queryStr.trim())) return null;
        queryStr = queryStr.replaceAll(SQLUtil.REPLACECHAR_COMMA, " ").replaceAll(REPLACECHAR_SEMICOLON, " ");
        return queryStr.split("\\s+");
    }

    private static String queryInStr(String[] queryStrs) {
        if (null == queryStrs || 0 == queryStrs.length) return null;
        StringBuffer buf = new StringBuffer();
        for (int i = 0; i < queryStrs.length; i++) {
            if (i != 0) buf.append(",");
            buf.append("'").append(queryStrs[i]).append("'");
        }
        return buf.toString();
    }
}

Mapper層處理:

//錯誤的處理
<if test="ruleName != null and ruleName != ''">
    AND a.rule_name IN (#{ruleName})
</if>

//正確的處理
<if test="ruleName != null and ruleName != ''">
    AND a.rule_name IN (${ruleName})
</if>

日志描述:

[DEBUG] [2016-08-02 17:42:42.226] [qtp1457334982-157] java.sql.Connection - ==>  Preparing: SELECT a.id, a.is_valid, a.rule_lable, a.rule_name, a.type, b.sp_id, b.sp_name, 
      a.rule_content, c.user_name, a.gmt_modified, a.ordering FROM idc_logistics_assign_rules a LEFT JOIN app_user c on c.work_no=a.modifier and c.is_deleted='n',
      idc_sp_info b WHERE a.is_deleted = 'n' AND b.is_deleted = 'n' AND a.sp_id = b.sp_id AND a.rule_name IN (?) ORDER BY ordering asc limit ?, ? [DEBUG] [2016-08-02 17:42:42.226] [qtp1457334982-157] java.sql.PreparedStatement - ==> Parameters: 'A','B'(String), 0(Integer), 10(Integer)

結果分析:mapper層對sql有預編譯處理,對於#有占位符?,但是對於$會直接替換。

參考:http://www.tuicool.com/articles/VvyMN3A

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved