MyBatis中使用$和#所遇到的问题及解决办法
在上篇文章给大家介绍了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有预编译处理,对于#有占位符?,但是对于$会直接替换。
ps:mybatis排序时使用order by 动态参数时需要注意,用$而不是#
字符串替换
默认情况下,使用#{}格式的语法会导致mybatis创建预处理语句属性并以它为背景设置安全的值(比如?)。这样做很安全,很迅速也是首选做法,有时你只是想直接在sql语句中插入一个不改变的字符串。比如,像order by,你可以这样来使用:
order by ${columnname}
这里mybatis不会修改或转义字符串。
重要:接受从用户输出的内容并提供给语句中不变的字符串,这样做是不安全的。这会导致潜在的sql注入攻击,因此你不应该允许用户输入这些字段,或者通常自行转义并检查。
上一篇: php pdo操作数据库示例
下一篇: 常用命令
推荐阅读
-
MyBatis中使用$和#所遇到的问题及解决办法
-
MyBatis中使用$和#所遇到的问题及解决办法
-
记录在训练深度学习算法过程中遇到的问题及解决办法。持续更新中....
-
Python结巴中文分词工具使用过程中遇到的问题及解决方法
-
使用asp.net MVC4中的Bundle遇到的问题及解决办法分享
-
Python结巴中文分词工具使用过程中遇到的问题及解决方法
-
使用asp.net MVC4中的Bundle遇到的问题及解决办法分享
-
安装、配置和测试Asterisk过程中遇到的问题及解决方法
-
web报表工具FineReport使用中遇到的常见报错及解决办法(三) finereport报表软件FAQ
-
ListView和Datetable之间的转换以及使用ListView中遇到的问题