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ù)是以?占位符的方式傳遞??梢钥吹絤ybaits的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)文章
新版idea創(chuàng)建spring boot項(xiàng)目的詳細(xì)教程
這篇文章給大家介紹了新版idea創(chuàng)建spring boot項(xiàng)目的詳細(xì)教程,本教程對新手小白友好,若根據(jù)教程創(chuàng)建出現(xiàn)問題導(dǎo)致失敗可下載我提供的源碼,在文章最后,本教程較新,文中通過圖文給大家介紹的非常詳細(xì),感興趣的朋友可以參考下2024-01-01
RabbitMQ冪等性與優(yōu)先級及惰性詳細(xì)全面講解
關(guān)于MQ消費(fèi)者的冪等性問題,在于MQ的重試機(jī)制,因?yàn)榫W(wǎng)絡(luò)原因或客戶端延遲消費(fèi)導(dǎo)致重復(fù)消費(fèi)。使用MQ重試機(jī)制需要注意的事項(xiàng)以及如何解決消費(fèi)者冪等性與優(yōu)先級及惰性問題以下將逐一講解2022-11-11
AsyncHttpClient的默認(rèn)配置源碼流程解讀
這篇文章主要為大家介紹了AsyncHttpClient的默認(rèn)配置源碼流程解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12
SpringBoot配置log4j2的實(shí)現(xiàn)示例
SpringBoot中默認(rèn)使用Logback作為日志框架,本文主要介紹了SpringBoot配置log4j2的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下2023-12-12
Mockito 結(jié)合 Springboot 進(jìn)行應(yīng)用測試的方法詳解
這篇文章主要介紹了Mockito 結(jié)合 Springboot 進(jìn)行應(yīng)用測試的方法詳解,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-11-11

