今天遇到一个问题,mysql数据库使用mybatis在mapper.xml写动态sql order by无法正确使用,没有报错,看日志也是传入了值
后来自己修改order by传入的值,发现对sql没有影响,说明这个sql没有正确执行
首先sql是这样写的
order by #{ORDER_BY}
外部定义是
private static final String ORDER_BY = "name ASC";
查看日志
Parameters: name ASC(String), 0(Integer), 10(Integer)
看到ORDER_BY的确传进来了,就是这个name ASC(String),但是它是String类型的,这时sql语句为 order by "name ASC ",
大家可以在mysql里面直接这样写写,sql语句会执行,但是没有作用,也不会报错
下面改成
order by ${ORDER_BY}
查看日志
Parameters: 0(Integer), 10(Integer)
没有了name ASC(String) 但是结果正确执行了
网上查找资料:
(1)对于形如#{variable} 的变量,Mybatis会将其视为字符串值,在变量替换成功后,缺省地给变量值加上引号。"variable"
(2)对于形如${variable}的变量,Mybatis会将其视作直接变量,即在变量替换成功后,不会再给其加上引号。 variable
所以在动态sql中,#{variable} 需要去掉 "",比如正常sql赋值一般是这样的and name= #{name},因为是=赋值,所以会获取内容,去掉""
${variable}可以直接使用,比如order by ${name} 传入的直接是name,不带双引号,可以直接使用,
并且order by不是 =赋值,所以如果直接order by #{name},结果是order by "name",自然无法执行了
总结,#{variable} 传入字符串,可以在日志查看到传入的参数,需要赋值后使用,可以有效防止sql注入
${variable}是直接传入变量,在日志查看不到传入的变量,直接在sql中执行,无法防止sql注入
所以,尽量用#{variable}格式,如果不是类似=赋值后再使用的sql,需要使用${variable}
网上还说有<![CDATA[]]>内需要注意#与$的区别,暂时没遇到,先备注一下。