组内自定义了动态表头,支持表头字段的排序(表头字段列名是什么,排序查询传进来的就是什么),那列表查询的时候只好把 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 的值如下:
orderType 的值如下:
然后我就天真的传入字段进行排序了,因为 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,就这个破玩意浪费了我好长时间,虽然很简单,但是第一次踩到,记录一下。
启发: 以后遇到解决不了的问题,不要死磕,找小伙伴一起讨论下,说不定哪句话就直接点醒你。
谨以此记录我这不健全的脑干,只好一步一个坑来的实在。