Mybatis關(guān)于動態(tài)排序 #{} ${}問題
Mybatis動態(tài)排序 #{} ${}問題
在寫Mybatis動態(tài)排序是遇到一個問題,開始,我是這樣寫的
<if test="orderField !=null and orderField != '' "> ? ? order by t.#{orderField} ?#{orderType} </if>
發(fā)現(xiàn)報錯,后來經(jīng)過查閱資料發(fā)現(xiàn),用#{}會多個' '導致SQL語句失效。
就是說,向上面這樣的,連續(xù)使用#{}進行注入的,會導致SQL語句失效。
所以,改成${}注入就可以了
<if test="orderField !=null and orderField != '' "> ? ? order by t.${orderField} ?${orderType} </if>
通過動態(tài)排序理解#{}和${}的區(qū)別
在日常開發(fā)中,尤其是在數(shù)據(jù)列表展示中,排序是最基本的功能。一般根據(jù)創(chuàng)建時間倒敘,但有可能碰到動態(tài)排序的需求。
接下來,我們將圍繞由后臺動態(tài)排序進行探討
例如
現(xiàn)在,我們要查詢一張店長表tb_director,我們在原有的父類中,新定義兩個字段
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonIgnore; import java.io.Serializable; import java.util.Date; import java.util.HashMap; import java.util.Map; /** ?* Entity基類 ?* ?* @author 進擊的Java君 ?*/ public class BaseEntity implements Serializable { ? ? private static final long serialVersionUID = 1L; ? ? /** 排序列*/ ? ? private String orderField; ? ? /** 排序規(guī)則,升降序*/ ? ? private String orderType; ? ? /** 搜索值 */ ? ? private String searchValue; ? ? /** 創(chuàng)建者 */ ? ? private String createBy; ? ? /** 創(chuàng)建時間 */ ? ? @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") ? ? private Date createTime; ? ? /** 更新者 */ ? ? private String updateBy; ? ? /** 更新時間 */ ? ? @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") ? ? private Date updateTime; ? ? /** 備注 */ ? ? private String remark; ? ? /** 開始時間 */ ? ? @JsonIgnore ? ? private String beginTime; ? ? /** 結(jié)束時間 */ ? ? @JsonIgnore ? ? private String endTime; ? ? /** 請求參數(shù) */ ? ? private Map<String, Object> params; } /** ?* 店長表 ?* @author 進擊的Java君 ?* @date 2021-03-18 ?*/ @Entity @Getter @Setter @Table(name = "tb_director") public class Director extends BaseEntity { ? ?? ? ? ?/** 主鍵id */ ? ? @Id ? ? @GeneratedValue(strategy = GenerationType.IDENTITY) ? ? private Long id; ? ? ? ? ?/** 店鋪名稱 */ ? ? @Column(name = "director_name", unique = true) ? ? private String directorName; ? ? /** 店鋪地址 */ ? ? @Column(name = "director_adress", unique = true) ? ? private String directorAdress; }
現(xiàn)在,我們只需要在mapper.xml中加上sql過濾條件即可
? <!-- 查詢店長信息 --> ? <sql id="selectDirectorVo"> ? ? ?select id, director_name,director_adress,director_num,director_create_time,director_up_time,openId ? ? ? ? ?from tb_director ? </sql> ? <!-- 查詢條件 --> ? <sql id="sqlwhereSearch"> ? ? ? ? ?<where> ? ? ? ? ? ? ?<if test="directorName !=null and directorName !=''"> ? ? ? ? ? ? ? ? ? ? ? AND director_name like concat('%', #{directorName}, '%') ? ? ? ? ? ? ?</if> ? ? ? ? ? ? ?<if test="openId !=null and openId !=''"> ? ? ? ? ? ? ? ? ? ? ? AND openId=#{openId} ? ? ? ? ? ? </if> ? ? ? ? ? ? ? ? <if test="id !=null and id !=''"> ? ? ? ? ? ? ? ? ? ? ? AND id=#{id} ?? ??? ??? ?</if> ? ? ?? ??? ?<if test="beginTime != null and beginTime != ''"><!-- 開始時間檢索 --> ? ? ? ? ?? ??? ??? ? ?AND date_format(directorCreateTime,'%y%m%d') >= date_format(#{beginTime},'%y%m%d') ? ? ? ? ?? ?</if> ? ? ? ? ? ? <if test="endTime != null and endTime != ''"><!-- 結(jié)束時間檢索 --> ? ? ? ? ? ? ? ? ?? ? ?AND date_format(directorCreateTime,'%y%m%d') <= date_format(#{endTime},'%y%m%d') ? ? ? ? ? ? </if> ? ? ? ? ? ? </where> ? ? ? ? ? ? <!-- 根據(jù)傳入字段動態(tài)過濾 --> ? ? ? ? ? ? <if test="orderField !=null and orderField != '' "> ? ? ? ? ? ? ? ? ? ? ? ? order by ${orderField} ?${orderType} ?? ??? ??? ?</if> ? ? ? ? </sql> ? <!-- 根據(jù)條件查詢店長 --> ? <select id="sel" parameterType="Director" resultMap="DirectorResult"> ? ? ? ? ? ? ? ? <include refid="selectDirectorVo"/> ? ? ? ? ? ? ? ? <include refid="sqlwhereSearch"/> ? ? ? ? </select>
持久層代碼編完后,我們只需要在調(diào)用時,傳入我們想進行排序的字段即可。
如下所示:
127.0.0.1:8080/api/director/sel?orderField=director_create_time&orderType=desc
但是這樣的話,就需要我們對表中的字段非常清楚,如果覺得這樣不舒服的話,我們可以對sql進行修改
<if test="orderField !=null and orderField != '' "> ?? ?order by ?? ?<choose> ?? ??? ?<when test="orderField == 'directorName'"> ?? ??? ??? ?director_name ${orderType} ?? ??? ?</when> ?? ??? ?<when test="orderField == 'openId'"> ?? ??? ??? ?openId ${orderType} ?? ??? ?</when> ?? ??? ?<otherwise> ?? ??? ??? ?create_time ${orderType} ?? ??? ?</otherwise> ?? ?</choose> </if>
注意事項
使用這樣連續(xù)拼接兩個注入?yún)?shù)時,只能用${},不能用#{}。
如果使用#{orderField},則會被解析成ORDER BY “orderField”,這顯然是一種錯誤的寫法。
- $ 符號一般用來當作占位符
- #{}是sql的參數(shù)占位符,Mybatis會將sql中的#{}替換為?號,在sql執(zhí)行前會使用PreparedStatement的參數(shù)設(shè)置方法,按序給sql的?號占位符設(shè)置參數(shù)值。
預編譯的機制。預編譯是提前對SQL語句進行預編譯,而其后注入的參數(shù)將不會再進行SQL編譯。我們知道,SQL注入是發(fā)生在編譯的過程中,因為惡意注入了某些特殊字符,最后被編譯成了惡意的執(zhí)行操作。而預編譯機制則可以很好的防止SQL注入。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
- MyBatis中#{}?和?${}?的區(qū)別和動態(tài)?SQL詳解
- mybatis中${}和#{}的區(qū)別以及底層原理分析
- MyBatis #{}和${} |與數(shù)據(jù)庫連接池使用詳解
- MyBatis中使用#{}和${}占位符傳遞參數(shù)的各種報錯信息處理方案
- mybatis中#{}和${}的區(qū)別詳解
- MyBatis中#{}和${}有哪些區(qū)別
- mybatis中${}和#{}取值的區(qū)別分析
- MyBatis中#{}占位符與${}拼接符的用法說明
- 詳解Mybatis中的 ${} 和 #{}區(qū)別與用法
- Mybatis之#{}與${}的區(qū)別使用詳解
- Mybatis中#{}與${}的區(qū)別詳解
- MyBatis中 #{} 和 ${} 的區(qū)別小結(jié)
相關(guān)文章
Java源碼解析之Gateway請求轉(zhuǎn)發(fā)
今天給大家?guī)淼氖顷P(guān)于Java的相關(guān)知識,文章圍繞著Gateway請求轉(zhuǎn)發(fā)展開,文中有非常詳細介紹及代碼示例,需要的朋友可以參考下2021-06-06關(guān)于Socket的解析以及雙方即時通訊的java實現(xiàn)方法
本篇文章主要介紹了關(guān)于Socket的解析以及雙方通訊的java實現(xiàn)方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下。2017-03-03Java?中?hashCode()?與?equals()?的關(guān)系(面試)
這篇文章主要介紹了Java中hashCode()與equals()的關(guān)系,ava中hashCode()和equals()的關(guān)系是面試中的??键c,文章對hashCode與equals的關(guān)系做出詳解,需要的小伙伴可以參考一下2022-09-09關(guān)于IDEA創(chuàng)建spark maven項目并連接遠程spark集群問題
這篇文章主要介紹了IDEA創(chuàng)建spark maven項目并連接遠程spark集群,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-08-08使用Java對數(shù)據(jù)庫進行基本的查詢和更新操作
這篇文章主要介紹了使用Java對數(shù)據(jù)庫進行基本的查詢和更新操作,是Java入門學習中的基礎(chǔ)知識,需要的朋友可以參考下2015-10-10