MyBatis中模糊搜索使用like匹配帶%字符時失效問題

1.問題背景

Mybatis是我們日常項目中經常使用的框架,在項目中我們一般會使用like查詢作爲模糊匹配字符進行搜索匹配,下面的Mapper.xml是我們使用like在項目中進行模糊匹配的常用方式:

<sql id="searchCondition">
    <trim prefix="where" prefixOverrides="and|or">  
        <if test="paramVo.detail != null and paramVo.detail != '' ">
          and idwl.detail like concat('%', #{paramVo.detail, jdbcType=VARCHAR}, '%')
        </if>
     </trim>  
</sql>

 

這樣使用模糊查詢在分頁搜索中可以解決90%的匹配搜索功能,但是,還是有10%是陰溝翻船的事情。比如現在我要匹配文件名detail中帶有'%'的文件,使用這個語句就會造成搜索失效,直接返回表中的limit所有數據。

 

造成這樣結果的原因就是由於像'%'或者'_'這樣的字符是通配字符,在模糊匹配的時候需要進行轉義執行,mysql執行解析器纔會把它當成是單個字符進行匹配,否則則會按照匹配兩個''字符進行模糊匹配,得出全表搜索的錯誤結果。

 

2.解決方法

2.1.在入參SearchVo上進行特殊符號relpace轉換

使用Vo入參接收類對前端傳入的detail字段進行判別處理,優先替換replace特殊字符:

public class SerachParamVO {
    private String productVersion;
    private String detail;
    private Integer releaseType;
    private String createUser;
    private String createUserAccount;
    private Date createTime;
    private String description;

    public void setDetail(String detail) {
        this.detail = detail.replaceAll("%", "\\\\%")
                .replaceAll("_", "\\\\_");
    }
}

2.2.使用ESCAPE

使用ESCAPE:escape簡單來說就是escape '字符'表示在like中從帶有'字符'之後不再作爲通配字符具有特殊含義,escape的理解可以參考另外一篇博客:

MYSQL escape用法 ,這裏就不再做詳細介紹。

 對應的解決方式如下:

①修改sql查詢語句,添加escape:

<sql id="searchCondition">
    <trim prefix="where" prefixOverrides="and|or">  
        <if test="paramVo.detail != null and paramVo.detail != '' ">
          and idwl.detail like concat('%', #{paramVo.detail, jdbcType=VARCHAR}, '%') escape '/'
        </if>
     </trim>  
</sql>

②傳入SearchVo進行通配符設置:

public class SerachParamVO {
    private String productVersion;
    private String detail;
    private Integer releaseType;
    private String createUser;
    private String createUserAccount;
    private Date createTime;
    private String description;

    public void setDetail(String detail) {
        this.detail = detail.replaceAll("%", "/%")
                .replaceAll("_", "/_");
    }
}

 

2.3.總結

以上兩種方式本質都是對查詢的關鍵字進行了處理,第一種方式更直接簡潔,第二種方式更容易理解。兩種方式我個人更推薦第一種。

另外還有一種處理方式是在代碼中使用攔截器或者AOP等技術進行統一攔截處理,有興趣的小夥伴可以搜索瞭解一下。涉及代碼較多,這裏就不再一一展開。

 

本博文寫作要感謝“阿飛雲”提供博文參考:

Mybatis中Like的使用方式以及一些注意點

寫的非常不錯,也在工作中解決了我的一個Bug單問題,可以結合一起作爲參考。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章