Mybatis實(shí)現(xiàn)動(dòng)態(tài)排序方式
Mybatis實(shí)現(xiàn)動(dòng)態(tài)排序
在數(shù)據(jù)展示時(shí),很有可能碰到,需要?jiǎng)討B(tài)排序的需求。當(dāng)數(shù)據(jù)比較少的時(shí)候,還可以前端排序,但是,當(dāng)數(shù)據(jù)非常大,尤其是涉及到分頁的時(shí)候,就必須要用后端解決了。
以下,提供一種后端動(dòng)態(tài)排序解決方案。
比如,現(xiàn)在我要查詢用戶信息(User)表。
可以在查詢時(shí),接口中,多添加兩個(gè)字段。
orderField
(排序列)orderType
(排序規(guī)則,升降序)
之后,在mapper.xml中的查詢列表方法,添加
SELECT? name , sex , age , user_grade as userGrade FROM user <if test="orderField !=null and orderField != '' "> ? ? order by ${orderField} ?${orderType} </if>
注意事項(xiàng):使用這樣連續(xù)拼接兩個(gè)注入?yún)?shù)時(shí),只能用${},不能用#{}。
詳情可以查看解釋
這時(shí),在我們查詢時(shí),可以在傳入?yún)?shù)
User user = new User(); //以user_grade字段排序 user.setOrderField("user_grade"); //降序 user.setOrderType("desc"); //可在User類中添加 //在未傳入時(shí),使用set注入,設(shè)置默認(rèn)值 public String getOrderField() { ?? ??? ?if (orderField == null || "".equals(orderField)) { ?? ??? ??? ?orderField = "create_time"; ?? ??? ?} ?? ??? ?return orderField; ?? ?} ?? ?public String getOrderType() { ?? ??? ?if (orderType == null || "".equals(orderType)) { ?? ??? ??? ?orderType = "desc"; ?? ??? ?} ?? ??? ?return orderType; ?? ?}
如果,你覺得傳入數(shù)據(jù)庫中字段user_grade很不舒服的話??梢赃@樣寫SQL
SELECT? name , sex , age , user_grade as userGrade FROM user <if test="orderField != null" > ?? ?ORDER BY ?? ?<choose> ?? ??? ?<when test="orderField == 'name'"> ?? ??? ??? ?name ${orderType} ?? ??? ?</when> ?? ??? ?<when test="orderField == 'age'"> ?? ??? ??? ?age ${orderType} ?? ??? ?</when> ?? ??? ?<when test="orderField == 'userGrade'"> ?? ??? ??? ?user_grade ${orderType} ?? ??? ?</when> ?? ??? ?<otherwise> ?? ??? ??? ?create_time ${orderType} ?? ??? ?</otherwise> ?? ?</choose> </if>
然后再傳入字段時(shí),就這樣
user.setOrderField("userGrade");
Mybatis動(dòng)態(tài)排序不生效問題
sql如下:
select * from ?table_name order by #{field}
造成問題原因
mybatis動(dòng)態(tài)參數(shù)
#{}方式傳參數(shù)會(huì)使用preparedstatement預(yù)編譯處理方式,參數(shù)是以?占位符的方式傳遞。可以看到mybaits的sql日志如下:
==> Preparing: SELECT * FROM table_name ORDER BY ? ==> Parameters: time(String)
preparedstatement預(yù)編譯方式的參數(shù)替換的原理1可知預(yù)編譯方式會(huì)對參數(shù)加上’'引號,生成的最終sql如下:
SELECT * FROM table_name ORDER BY 'time'
以上sql數(shù)據(jù)庫不能正常解析 order by 后面的字段,這就是我們排序失效的原因
解決辦法
將#{}參數(shù)方式改成${}參數(shù)方式即可。
原因: ${}參數(shù)的方式是簡單的字符串替換。
在動(dòng)態(tài)解析階段,該 sql 語句會(huì)被解析成:
select * from table_name order by time
小結(jié)一下:
- #{}方式傳參數(shù)只能處理值參數(shù) 不能傳遞表名,字段等參數(shù)
- ${}字符串替換,可以動(dòng)態(tài)處理表名,字段參數(shù),但是使用這種方式必須注意sql注入的風(fēng)險(xiǎn),對參數(shù)做好校驗(yàn)處理
備注:preparedstatement具體實(shí)現(xiàn)原理見:com.mysql.jdbc.PreparedStatement中的setString方法源碼
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Spring Aop之AspectJ注解配置實(shí)現(xiàn)日志管理的方法
下面小編就為大家分享一篇Spring Aop之AspectJ注解配置實(shí)現(xiàn)日志管理的方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-01-01微信開發(fā)準(zhǔn)備第一步 Maven倉庫管理新建WEB項(xiàng)目
這篇文章主要為大家詳細(xì)介紹了微信開發(fā)準(zhǔn)備第一步,Maven倉庫管理新建WEB項(xiàng)目,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04