大家好,我是老三,一個平平無奇的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日知錄
,快樂繼續。
“簡單的事情重複做,重複的事情認真做,認真的事情有創造性地做。”——
我是三分惡,一個能文能武的全棧開發!
點贊、關注不迷路,咱們下期見!