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

作一個積極的人java

編碼、改bug、提高本身sql

我有一個樂園,面向編程,春暖花開!編程

模糊查詢在項目中仍是常常使用的,本文就簡單整理Mybatis中使用Like進行模糊查詢的幾種寫法以及一些常見的問題。app

初始數據

UTOOLS1571459569641.png

方式一

在Mybatis中的第一種寫法:框架

<!--有sql注入問題-->
 <select id="findUserByLikeName1" parameterType="java.lang.String" resultMap="user">
      select * from t_user where name like '%${name}%'
  </select>
複製代碼

這種會有sql注入的問題,須要明白在 Mybatis中 $# 使用的區別。這種寫法也不能加jdbcType=VARCHAR,不然也會報錯。學習

作了個簡單的測試:測試

@Test
public void findUserByLikeName1(){
    List<User> test = userMapper.findUserByLikeName1("Cloud");
    //select * from t_user where name like '%Cloud%'
    System.out.println(test.size());// 查出一條
    
    List<User> test1 = userMapper.findUserByLikeName1("' or '1=1");
    //select * from t_user where name like '%' or '1=1%'
    // 分析: '1=1%' 成立
    System.out.println(test1.size());// 查出了所有數據
}
複製代碼

注意:排序的字段也容易出現這個問題,在使用的時候也必定要注意。大數據

order by ${orderBy}優化

第一種方式在實際開發過程當中千萬要注意,不要寫成這樣了。編碼

方式二

在Mybatis中的第二種寫法:

<!--直接在代碼中拼接%, 不存在sql注入-->
 <select id="findUserByLikeName2" parameterType="java.lang.String" resultMap="user">
      select * from t_user where name like #{name,jdbcType=VARCHAR}
  </select>
複製代碼

在代碼中加上%

@Test
public void findUserByLikeName2(){
    String name = "Cloud";
    List<User> test = userMapper.findUserByLikeName2("%" +name+"%");
    // select * from t_user where name like ?
    // %Cloud%(String)
    System.out.println(test.size());
}
複製代碼

這種方式在一些項目中也會看到。若是沒有使用如Mybatis等ORM框架,直接寫sql查詢就這樣拼接了。

方式三

在Mybatis中的第三種寫法:

<!--concat Mysql和 Oracle區別 ,不存在sql注入-->
  <select id="findUserByLikeName3" parameterType="java.lang.String" resultMap="user">
      select * from t_user where name like concat('%',#{name,jdbcType=VARCHAR},'%')
  </select>
複製代碼

測試:

@Test
public void findUserByLikeName3(){
    String name = "Cloud";
    List<User> test = userMapper.findUserByLikeName3(name);
    // select * from t_user where name like concat('%',?,'%')
    // Cloud(String)
    System.out.println(test.size());
}
複製代碼

在實際開發中推薦使用這種方式。

小注意

當使用方式三的時候,若是查詢的關鍵字就是% ,那狀況會是什麼? 初始化數據中name有9條數據中包含%

查詢的sql以下:

select * from t_user where name like concat('%','%','%')

查出來所有的數據,並非只包含了%的數據,若是查詢_也是同樣的。

那這種狀況確定是不知足查詢需求的,則須要調整。

①在代碼中進行轉義

@Test
public void findUserByLikeName3(){
    String name = "%";
    name = name.replaceAll("_", "\\\\_");
    name = name.replaceAll("%", "\\\\%");

    List<User> test = userMapper.findUserByLikeName3(name);
    System.out.println(test.size());
}
複製代碼

②使用ESCAPE

<select id="findUserByLikeName4" parameterType="java.lang.String" resultMap="user">
select * from t_user where name like concat('%',#{name,jdbcType=VARCHAR},'%') ESCAPE '/'
</select>
複製代碼

測試:

@Test
public void findUserByLikeName4(){
    // replaceAll("%", "/%").replaceAll("_", "/_")
    String name = "%";
    List<User> test = userMapper.findUserByLikeName4(name);
    System.out.println(test.size());// 查到所有
    List<User> test1 = userMapper.findUserByLikeName4("/" +name);
    System.out.println(test1.size());//查到匹配%的記錄
}
複製代碼

這兩種本質都是對查詢的關鍵字進行了處理,這種處理在代碼中可使用攔截器或者AOP等技術統一處理。

小總結

一、不要寫方式1的這種模糊查詢,容易發生sql注入!

建議使用第三種方式進行模糊查詢

二、上面這三種模糊查詢,都是使用%關鍵字%,這種方式是不會走索引的,大數據量時候有查詢效率問題

看狀況,可使用全文索引;或者使用ES進行

說明:網上有一些優化like的查詢的,可是親測後沒啥用

三、注意關鍵詞中有%、_這些特殊字符如何處理。

一、業務上不容許輸入這些字符,直接過濾(前臺、後臺過濾)

二、使用上面的ESCAPE或者轉義

備註: 因爲本人能力有限,文中如有錯誤之處,歡迎指正。


謝謝你的閱讀,若是您以爲這篇博文對你有幫助,請點贊或者喜歡,讓更多的人看到!祝你天天開心愉快!


Java編程技術樂園:一個分享編程知識的公衆號。跟着老司機一塊兒學習乾貨技術知識,天天進步一點點,讓小的積累,帶來大的改變!

掃描關注,後臺回覆【祕籍】,獲取珍藏乾貨! 99.9%的夥伴都很喜歡

image.png | center| 747x519

©天天都在變得更好的阿飛雲
相關文章
相關標籤/搜索