MyBatis中應用$和#所碰到的成績及處理方法。本站提示廣大學習愛好者:(MyBatis中應用$和#所碰到的成績及處理方法)文章只能為提供參考,不一定能成為您想要的結果。以下是MyBatis中應用$和#所碰到的成績及處理方法正文
在上篇文章給年夜家引見了Mybatis中#{}和${}傳參的差別及#和$的差別小結,假如年夜家有須要可以參考下。
$和#簡略解釋:
#相當於對數據 加上 雙引號,$相當於直接顯示數據。
1、總結
mybatis中應用sqlMap停止sql查詢時,常常須要靜態傳遞參數。靜態SQL是mybatis的壯大特征之一,也是它優於其他ORM框架的一個主要緣由。mybatis在對sql語句停止預編譯之前,會對sql停止靜態解析,解析為一個BoundSql對象,也是在此處對靜態SQL停止處置的。在靜態 SQL 解析階段,#{ }和${ }會有分歧的表示,#{ }解析為一個JDBC預編譯語句(prepared statement)的參數標志符。
一個 #{ } 被解析為一個參數占位符 ? 。${ } 僅僅為一個純碎的 string 調換,在靜態 SQL 解析階段將會停止變量調換。
2、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有預編譯處置,關於#有占位符?,然則關於$會直代替換。
PS:MyBatis排序時應用order by 靜態參數時須要留意,用$而不是#
字符串調換
默許情形下,應用#{}格局的語法會招致MyBatis創立預處置語句屬性並以它為配景設置平安的值(好比?)。如許做很平安,很敏捷也是首選做法,有時你只是想直接在SQL語句中拔出一個不轉變的字符串。好比,像ORDER BY,你可以如許來應用:
ORDER BY ${columnName}
這裡MyBatis不會修正或本義字符串。
主要:接收從用戶輸入的內容並供給給語句中不變的字符串,如許做是不平安的。這會招致潛伏的SQL注入進擊,是以你不該該許可用戶輸出這些字段,或許平日自行本義並檢討。