Mybatis order by 動態傳參出現的問題及解決方法
問題由來
一個簡單的需求,要求把和當前用戶相關的數據置頂展示。
這裡,我用瞭一個簡單的用戶表來復現這個需求。
很簡單,查詢語句後面加上: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>
上去吧,吳老二!
問題比較簡單,處理起來也是三下五除二,但是分析的過程還有點意思,所以發出來給大傢瞧瞧。
到此這篇關於Mybatis order by 動態傳參出現的一個小bug的文章就介紹到這瞭,更多相關Mybatis order by 動態傳參出現的一個小bug內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- mybatis mapper.xml 註釋帶參數的坑及解決
- 解決Mybatis映射文件mapper.xml中的註釋問題
- MyBatis註解實現動態SQL問題
- MySQL中order by的使用詳情
- Mybatis中返回Map的實現