【实力踩坑】ORDER BY 不生效

发布时间:2023年12月28日

很简单的一个问题但还是值得记录一下。

组内自定义了动态表头,支持表头字段的排序(表头字段列名是什么,排序查询传进来的就是什么),那列表查询的时候只好把 sql 写成一个嵌套子查询,在最后进行动态 order by orderFiled 的形式,代码如下:

select *
    from (
           select t1.c1 as column1, t1.c2 as column2, t2.c3 as column3
           from demo_table t1
                  inner join demo_table t2 on t1.c1 = t2.c1
         ) t
    order by #{orderField} #{orderType}

orderField 的值如下:

  • column1
  • column2
  • column3

orderType 的值如下:

  • asc
  • desc

然后我就天真的传入字段进行排序了,因为 DEBUG 日志级别,控制台打印 SQL 日志如下:

==>  Preparing: select * from ( select t1.c1 as column1, t1.c2 as column2, t2.c3 as column3 from demo_table t1 inner join demo_table t2 on t1.c1 = t2.c1 ) t order by ? ? 
==> Parameters: column1(String), asc(String)

看着没毛病哈,但是实际查询 order by 后面的字段就是不生效,我尝试了好几种方式就 TM 不生效,我很气啊,就这个小破玩意耽误了我好长时间,咋整呢?

最后和小伙伴回去讨论,一语点醒梦中人,妈的是#{}的坑,还记得它的孪生兄弟${}不,先看下它俩的区别:

在MyBatis中,#{}和${}都是用来替换参数的,但它们的功能和用途存在一些差异。

  • #{}用于预处理,而KaTeX parse error: Expected 'EOF', got '#' at position 14: {}用于直接替换。这意味着#?{}解析为JDBC预编译语句(…{}则仅仅是一个纯粹的字符串替换。

  • 在解析阶段,#{}会将String类型的数据自动加上引号,而其他数据类型不会;而${}解析之后是什么就是什么,不会当做字符串处理。

  • 从安全性角度看,使用#{}不存在安全问题,而使用存在安全问题。因为{}在动态SQL解析阶段会进行变量替换,可能会被注入恶意代码。

  • 在某些特殊场合下,如使用排序时ORDER BY filed,只能使用{},不能用#{}。这是因为#{}在解析之后会将String类型的数据自动加上引号,导致解析错误。

  • 综上所述,#{}和${}在功能、使用场景和安全性方面存在差异。在实际使用中,需要根据具体需求和场景选择合适的参数替换方式。

从这里应该能发现了吧,#{}是个占位符的形式,会把参数默认解析为一个字符串常量,而order by '字符串常量'是没有任何效果的,从而判定出就是它的坑,而使用${}会把字段值完全拼接在 SQL 中,也就是是啥就是啥,当然这种方式会有注入的风险,但是对此处的实际场景来说也没啥风险,果断换成${}再次查询生效了。

外日他 dei,就这个破玩意浪费了我好长时间,虽然很简单,但是第一次踩到,记录一下。

启发: 以后遇到解决不了的问题,不要死磕,找小伙伴一起讨论下,说不定哪句话就直接点醒你。

谨以此记录我这不健全的脑干,只好一步一个坑来的实在。

文章来源:https://blog.csdn.net/qq_52596258/article/details/135260711
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。