问题描述

@Select("select * from account order by #{orderBy} #{orderRule} limit #{start},#{offset}")
public List<Account> getAccountList(@Param("orderBy") String orderBy, @Param("orderRule") String orderRule,
@Param("start) int start, @Param("offset") int offset);

如上代码所示,在执行查询操作时,为了能够与前端联动进行排序,直接在SQL参数中传递排序字段和排序规则。

但是,在调试时偶然发现,当传递的“orderBy”值为不存在的字段时,竟然不会报错!!!

经过进一步调试发现,实际上并不会按照预期的排序规则返回数据列表!!!

原因追踪

设置log4j的日志级别为DEBUG后发现,最终执行的SQL语句是一个预编译操作,mybatis输出日志如下:

==>  Preparing: select * from account order by ? ? limit ?, ?
==> Parameters: loginName(String), DESC(String), 0(Integer), 50(Integer)

很显然,传递的参数loginName和DESC是作为字符串处理的。

也就是说,很有可能mybatis对String类型的参数会进行转换。举个例子:传递的String参数为loginName,最终在SQL语句执行时为:'loginName'。

再进一步验证,如果在SQL语句中传递的排序字段不是字段名loginName,而是'loginName'时,是不会按照排序规则返回数据的,并且也不会报错!

追溯mybatis官方文档发现:默认情况下,使用#{}格式的语法会导致mybatis对字符串进行修改或转义!!!



详见:http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html#select

解决问题

将参数传递的语法格式#{}修改为${},即:

@Select("select * from account order by ${orderBy} ${orderRule} limit #{start},#{offset}")
public List<Account> getAccountList(@Param("orderBy") String orderBy, @Param("orderRule") String orderRule,
@Param("start) int start, @Param("offset") int offset);

观察mybatis日志输出:

==>  Preparing: select * from account order by login_name DESC limit ?, ?
==> Parameters: 0(Integer), 50(Integer)

此时,对于使用${}格式引用的参数,mybatis直接在SQL语句中插入一个不改变的字符串,而不再作为一个预编译参数处理。

注意: 以这种方式接收用户输入的内容并直接提供给SQL语句作为不变的字符串是不安全的,会导致潜在的SQL注入攻击,因此要么不允许用户输入这些字段,要么自行转义并检验。

总结

如果只是想直接在SQL语句中插入一个不改变的字符串,比如,像ORDER BY,可以使用${}引用参数:ORDER BY ${columnName},这里mybatis不会修改或转义字符串。

最新文章

  1. Windows错误码解析
  2. 简单快捷好用的vim配置和终端配置推荐
  3. 关于hql一些不常见但好用的技巧(个人总结)
  4. git clone 错误ca-certificates.crt
  5. CocoaPods的使用
  6. android 之 桌面的小控件AppWidget
  7. C# 3.0 扩展方法[转载]
  8. 下载文件的一种简单方法js
  9. nape.dynamics.InteractionFilter
  10. 【SSH2(实用文章)】--Struts2文件上传和下载的例子
  11. 【JavaWeb】权限管理系统
  12. Hive导入HDFS/本地数据
  13. Servlet和Filter生命周期
  14. [Swift]LeetCode433. 最小基因变化 | Minimum Genetic Mutation
  15. Jenkins 无法捕获构建脚本错误问题
  16. delphi property read writer 如何使用
  17. bzoj 4008 亚瑟王 - 动态规划 - 概率与期望
  18. ASP.NET MVC:@helper 不能调试
  19. iOS应用之间的跳转
  20. ASP.NET 中整合JavaScript的技巧

热门文章

  1. NOIp 2018 游记
  2. 【Luogu2197】NIM游戏(博弈论)
  3. ELK部署详解--filebeat
  4. nodejs的某些api~(六)HTTPS
  5. 安装PHP ImageMagick笔记
  6. CF 1013E Hills
  7. 【CH0103】最短哈密顿路径
  8. 函数后面的const修饰符的作用
  9. java的抽象方法
  10. android studio adb.exe已停止工作(全面成功版 进程的查询和开启)