最近遇到一个错误:
在Mybatis的Mapper文件中的sql涉及 like语句:
Mapper.xml文件写法:
<sql id="dynamicWhere">
<where>
<if test="subscribe not in {null, ''}">subscribe = #{subscribe}</if>
<if test="openid not in {null, ''}">AND openid = #{openid}</if>
<if test="unionid not in {null, ''}">AND unionid = #{unionid}</if>
<if test="nickname not in {null, ''}">AND nickname like '%#{nickname}%'</if>
</where>
</sql>错误:
2017-07-20 18:17:31,058 DEBUG [org.apache.ibatis.logging.slf4j.Slf4jLoggerImpl-49] - ==> Preparing: SELECT COUNT(1) FROM wechat_user_info WHERE nickname like '%?%'
org.springframework.dao.TransientDataAccessResourceException:
### Error querying database. Cause: java.sql.SQLException: Parameter index out of range (1 > number of parameters, which is 0).这里会发现nickname的like语句有问题。
后面发现是因为#的原因,此时需要用到$符号
正确的写法:
<sql id="dynamicWhere">
<where>
<if test="subscribe not in {null, ''}">subscribe = #{subscribe}</if>
<if test="openid not in {null, ''}">AND openid = #{openid}</if>
<if test="unionid not in {null, ''}">AND unionid = #{unionid}</if>
<if test="nickname not in {null, ''}">AND nickname like '%${nickname}%'</if>
</where>
</sql>结论:
在Mybatis中Mapper.xml文件中,如果有sql涉及的模糊查询,中间包含like语句时,只能使用$,不能使用#。
但是使用$时,相当于直接传递字符串,存在sql注入的风险
而使用#{}语法将导致MyBatis生成PreparedStatement属性,并根据PreparedStatement参数安全地设置值(例如?)。虽然这更安全,更快速,几乎总是首选,但有时您只想直接将未修改的字符串注入到SQL语句中。例如,对于ORDER BY,您可以使用以下内容:
ORDER BY $ { columnName }
这里MyBatis不会修改或转义字符串。
本文探讨了在MyBatis中进行模糊查询时使用$符号而非#符号的原因及风险,并给出了具体的Mapper.xml文件示例。
1466

被折叠的 条评论
为什么被折叠?



