大家好,我是老三,一个平平无奇的CRUD仔。

今天,我正在愉快地CRUD,突然发现出现一个Bug,我们来看看是怎么回事吧!

问题由来

一个简单的需求,要求把和当前用户相关的数据置顶展示。

这里,我用了一个简单的用户表来复现这个需求。

很简单,查询语句后面加上:order by t.login_name='wulaoer' desc 就行了。

如下所示,吴老二就到顶了。

那Mybatis脚本怎么写呢?

就这么写

    <select id="selectUserPageOrder" resultType="cn.fighter3.entity.User">
select * from user t
order by t.login_name=#{req.currentUser} desc
</select>

OK,需求完成,测试,摸……

嗯,出bug了……

问题现场

定晴一看控制台,报错了。

最关键的一行:

java.sql.SQLException: Parameter index out of range (1 > number of parameters, which is 0).

问题分析

问题很简单,随手一查,原因是:

  • #{}传过来的参数带单引号

#{}采用预编译机制,是占位符,#{}传入参数是以字符串传入,会将SQL中的#{}替换为?号,调用PreparedStatement的set方法来赋值。

这种方式,order by 最后的sql会多加单引号 ' 。

那怎么解决呢?

可以用 ${}${}是拼接符,直接字符串替换。

    <select id="selectUserPageOrder" resultType="cn.fighter3.entity.User">
select * from user t
order by t.login_name=${req.currentUser} desc
</select>

我不想用${}这种方式,因为有sql注入的风险,那该怎么办呢?

好吧,其实主要是这种方式也报错了。

java.sql.SQLSyntaxErrorException: Unknown column 'wulaoer' in 'order clause'

我们平时模糊查询怎么写呢?

——使用CONCAT()函数来拼接keyword。

以此类推,那我用一个函数来去掉'不就行了。

那用一个什么函数呢?

——REPLACE

所以写法就变成了这样:

    <select id="selectUserPageOrder" resultType="cn.fighter3.entity.User">
select * from user t
order by t.login_name=REPLACE(#{req.currentUser},'\'','') desc
</select>

问题解决

OK,最终问题解决。

    <select id="selectUserPageOrder" resultType="cn.fighter3.entity.User">
select * from user t
order by t.login_name=REPLACE(#{req.currentUser},'\'','') desc
</select>

上去吧,吴老二!


问题比较简单,处理起来也是三下五除二,但是分析的过程还有点意思,所以发出来给大家瞧瞧。

PS:有读者朋友催更SringCloud Alibaba实战系列,抱歉,最近加班、刷题,只能暂时停更。不过大家不要担心没得学,我的朋友Jam哥已经更了三十几篇高质量教程,百度搜Java日知录,快乐继续。

“简单的事情重复做,重复的事情认真做,认真的事情有创造性地做。”——

我是三分恶,一个能文能武的全栈开发!

点赞关注不迷路,咱们下期见!

Mybatis order by 动态传参出现的一个小bug的更多相关文章

  1. MyBatis dao层 方法传参

    MyBatis dao层 方法传参有三种方法. 1. 以下标的方法获取参数. <update id="insertSuccessKilled">       INSER ...

  2. js函数动态传参

    js函数体内可以通过arguments对象来接收传递进来的参数,利用这一对象属性可以动态传参. function box() { return arguments[0]+' | '+arguments ...

  3. uploadify的用法与动态传参 提供demo下载

    ---恢复内容开始--- 官网:http://www.uploadify.com/   一款不错的上传插件.官方文档http://www.uploadify.com/documentation/ 用法 ...

  4. Postman 串行传参和动态传参详解

    Postman是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件 用Postman做接口测试的时候,要把多条用例一起执行,就需要把用例连接起来,一次性执行 目录 串行传参 动态传参 使用 ...

  5. python之路--动态传参,作用域,函数嵌套

    一 . 动态传参(重点)  * ,  ** * 与 ** * 在形参位置. * 表示不定参数, 接收的是位置参数 接收到的位置参数的动态传参: 都是元组 def eat(*food): # 在形参这里 ...

  6. python----函数的动态传参

    函数的动态传参 *args 将所有的实参的位置参数聚合到一个元组,并将这个元组赋值给args 有些时候,对于函数,传入的实参数量可能是不固定的,也就是动态的,这个时候我们就需要用到函数的动态传参.下面 ...

  7. 在Java中动态传参调用Python脚本

    最近,又接触到一个奇葩的接口,基于老板不断催促赶时间的情况下,在重写java接口和复用已有的python脚本的两条路中选择了后者,但是其实后者并没有好很多,因为我是一个对python的认识仅限于其名称 ...

  8. python函数的动态传参.作用域与命名空间

    一.动态传参1.*表示动态传参. 可以接受所有的位置参数传参的时候自动的把实参打包成元组 交给形参 def chi(*food): print(food) chi() # 动态传参可以不传参数 chi ...

  9. python记录_day10 动态传参 命名空间 作用域

    一.动态传参 动态传参用到 *args 和 **kwargs ,*号表示接收位置参数,args是参数名:**表示接收关键字参数,kwargs是参数名 def chi(*food): print(foo ...

随机推荐

  1. TVM源码框架安装方法

    TVM源码框架安装方法 本文提供如何在各种系统上从零构建和安装TVM包的说明.它包括两个步骤: 首先从C++代码中构建共享库(linux的libtvm.so,macOS的libtvm.dylib和wi ...

  2. Kaggle上的犬种识别(ImageNet Dogs)

    Kaggle上的犬种识别(ImageNet Dogs) Dog Breed Identification (ImageNet Dogs) on Kaggle 在本节中,将解决在Kaggle竞赛中的犬种 ...

  3. Xilinx Zynq FPGA Boards板

    Xilinx Zynq FPGA Boards板 Xilinx Zynq FPGA Boards 介绍 Styx是一个易于使用的Zynq开发模块,具有Xilinx的Zynq ZC7020 SoC和FT ...

  4. Django(56)Mixins工具集的使用

    前言 mixins翻译成中文是混入,组件的意思.在DRF中,针对获取列表,检索,创建等操作,都有相应的mixin,一般我们自定义创建的类视图都会继承自GenericAPIView和Mixins一起使用 ...

  5. JUC 并发编程--02,生产者和消费者 synchronized的写法 , juc的写法. Condition的用法

    synchronized的写法 class PCdemo{ public static void main(String[] args) { //多个线程操作同一资源 Data data = new ...

  6. JMeter定时器设置延迟与同步

    JMeter定时器一般用来设置延迟与同步.它的作用域和优先级如下: 定时器的优先级高于Sampler. 在同一作用域(比如控制器下)有多个定时器存在,每个定时器都会执行. 在某一Sampler节点下的 ...

  7. Qt自定义信号槽的使用浅析+实例

    1. Qt中自定义信号槽的使用 Qt框架提供的信号槽在某些特定场景下是无法满足我们的项目需求的,因此我们还设计自己需要的的信号和槽,使用connect()对自定义的信号槽进行连接. 如果想要使用自定义 ...

  8. codeforeces 845B

    题解 codefores 845B 原题 Luba has a ticket consisting of 6 digits. In one move she can choose digit in a ...

  9. Eureka中读写锁的奇思妙想,学废了吗?

    前言 很抱歉 好久没有更新文章了,最近的一篇原创还是在去年十月份,这个号确实荒废了好久,感激那些没有把我取消关注的小伙伴. 有读者朋友经常私信问我: "你号卖了?" "文 ...

  10. Spring学习日记01_IOC_xml的三种注入方式

    什么是IOC 控制反转,把对象创建和对象之间的调用过程,交给Spring进行管理 使用IOC目的:为了耦合度降低 做入门案例就是IOC实现 IOC底层原理 xml解析 工厂模式 反射 原始方式 cla ...