一、使用 like 模糊查询

1. 使用${…}

  1. <if test="map.bank != '' and map.bank != null ">
  2. and bank like '%${bank}%')
  3. </if>
  4. <!-- 错误的使用 -->
  5. <if test="map.bank != '' and map.bank != null ">
  6. and bank like '%${bank, jdbcType = VARCHAR}%')
  7. </if>

由于$是参数直接注入的,导致这种写法,大括号里面不能注明jdbcType,不然会报错
后者会报错:org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.reflection.ReflectionException: There is no getter for property named ‘VARCHAR’ in ‘class com.utry.ucsc.dao.bean.KnowledgeLibraryBean’

2. #{…}

  1. <if test="map.bank != '' and map.bank != null ">
  2. and b.bank like "%"#{bank, jdbcType = VARCHAR}"%")
  3. </if>

因为#{…}解析成sql语句时候,会在变量外侧自动加单引号’ ‘,所以这里 % 需要使用双引号” “,不能使用单引号 ‘ ‘,不然会查不到任何结果。

3. 使用 concat 拼接

  1. <if test="map.bank != '' and map.bank != null ">
  2. and b.bank like concat('%',#{map.bank},'%')
  3. </if>

二、预编译和字符串替换

在mybatis中#{}和${}的区别

解释1

将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。如:order by #user_id#,如果传入的值是111,那么解析成sql时的值为order by “111”,如果传入的值是id,则解析成的sql为order by “id”。
$将传入的数据直接显示生成在sql中。如:order by $user_id$,如果传入的值是111,那么解析成sql时的值为order by user_id,如果传入的值是id,则解析成的sql为order by id。

字符串替换
默认情况下,使用#{}格式的语法会导致MyBatis创建预处理语句属性并以它为背景设置安全的值(比如?)。这样做很安全,很迅速也是首选做法,有时你只是想直接在SQL语句中插入一个不改变的字符串。比如,像ORDER BY,你可以这样来使用:ORDER BY ${columnName} 这里MyBatis不会修改或转义字符串。
这种方式类似于:接受从用户输出的内容并提供给语句中不变的字符串(如下)。这样做是不安全的。这会导致潜在的SQL注入攻击,因此你不应该允许用户输入这些字段,或者通常自行转义并检查。

  1. //这种方式类似于:
  2. Statement st = conn.createStatement();
  3. ResultSet rs = st.executeQuery(sql);

解释2

{}是预编译处理,$ {}是字符串替换。mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;mybatis在处理 $ { } 时,就是把 ${ } 替换成变量的值。使用 #{} 可以有效的防止SQL注入,提高系统安全性。

解释3

$ 符号一般用来当作占位符,常使用Linux脚本的人应该对此有更深的体会吧。既然是占位符,当然就是被用来替换的。知道了这点就能很容易区分$和#,从而不容易记错了。
预编译的机制。预编译是提前对SQL语句进行预编译,而其后注入的参数将不会再进行SQL编译。我们知道,SQL注入是发生在编译的过程中,因为恶意注入了某些特殊字符,最后被编译成了恶意的执行操作。而预编译机制则可以很好的防止SQL注入。

字符串替换的使用

  1. 使用QueryWrapper构造条件后,可以通过调用它的sqlSegment方法获得筛选条件,在sql中当做条件使用 ${qw.sqlSegment}
  2. 分库分表时,注入表名称等
  3. MyBatis排序时使用order by 动态参数时需要注意,用$而不是#
  4. MyBatis中无法防止Sql注入