当前位置: 首页 > 后端技术 > Java

MyBatis中的#placeholder可能会导致查询结果为空

时间:2023-04-01 22:05:04 Java

问题的根源是我刚学springboot。在测试DAO层的时候,发现无论怎么测试都返回一个空集,但是在sql控制台可以正确返回结果。源码如下:DAO层@Select("select*fromtb_bookwhere${condition}like"+"concat('%',#{conditionKey},'%')limit#{pageStart},"+"#{pageSize}")ArrayListgetByCondition(intpageStart,intpageSize,Stringcondition,StringconditionKey);DAO测试类@TestvoidtestGetByCondition(){StringconditionKey="java";System.out.println(bookMapper.getByCondition(0,4,"name",conditionKey));}一般情况下可以通过控制台输出两个结果,但是测试的时候是空集,但是没有报错报道。到底是怎么回事。在网上找不到类似的问题,最后在stackoverflow上找到了靠谱的答案,直接看了mybatis官方文档。仔细研究后发现问题其实出在最基本的字符串占位符上,即#{}和${}。#{}不可能不假思索就把所有数据都替换掉~~~~文档中写到:默认情况下,使用#{}语法会导致MyBatis生成PreparedStatement属性,并针对PreparedStatement安全设置值参数(例如?)。虽然这更安全、更快并且几乎总是首选,但有时您只想直接将未修改的字符串注入SQL语句。例如,对于ORDERBY,您可以使用如下内容:ORDERBY${columnName}。这里MyBatis不会修改或转义字符串。也就是说,在运行时,我们代码中的where#{condition}被放入了预编译结果,导致解析时被认为是where"name"。..,这明显是错误的,但是程序并没有报错,sql日志也没有任何线索,所以这个问题可以说是非常难找了。解决方案知道是占位符问题后,解决起来就比较简单了,就是不用#{},用${}。虽然sql注入可能会有问题,但这也是无奈之举。最好的办法就是不要偷懒。最好写两条或多条sql语句。如果有更好的解决办法,欢迎讨论~~