【MyBatis】多關鍵字的模糊查詢

任務驅動才能明確方向。我舉一個例子。

情景分析

題目

現在我們要執行查詢操作,例如我要查詢商品的供應商資訊。供應商的資訊包括公司名稱,負責人名字,聯繫電話,公司地址等。

我也許會輸入電話號碼的前幾位查詢,也許會輸入公司名稱的某個字查詢,也許會輸出負責人的姓氏查詢……

我希望查出來的結果,是按照Id升序排序好了的。

要求

1.我要根據公司名稱查詢,只要公司名稱包含「廣東」、「深圳」的都可以被查詢出來

2.我要根據負責人名字查詢,只要負責人名字包含「周」、「吳」、「鄭」、「王」的都可以被查詢出來

3.我要根據電話號碼查詢,只要電話號碼包含「139」,「136」,「137」的都可以被查詢出來

相關程式碼

下面MyBatis的配置方式是Spring整合MyBatis的,詳情請參閱下面這篇文章

【Spring】【MyBatis】Spring整合MyBatis01 - 萌狼藍天 - 部落格園 (//www.cnblogs.com/mllt/p/SpringAndMybatis01.html)

Mapper.java

    /**
     * 查詢供應商資訊
     * @param way 查詢方式。1:根據供應商公司名稱模糊查詢 2:根據供應商負責人名字模糊查詢 3:根據電話模糊查詢
     * @param npcs 查詢的關鍵字
     * @return List<SmbmsProvider>
     */
    public List<SmbmsProvider> getProviderByNCP(@Param("way") int way, @Param("npcs") List<String> npcs);

SmbmsProvider是供應商對象。

Impl.java

package cc.mllt.impl;

import cc.mllt.mapper.ProviderMapper;
import cc.mllt.pojo.SmbmsProvider;
import org.mybatis.spring.SqlSessionTemplate;

import java.util.List;
//實現類
public class ProviderImpl implements ProviderMapper {
    private SqlSessionTemplate sqlSessionTemplate;
    public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate){
        this.sqlSessionTemplate=sqlSessionTemplate;
    }
    @Override
    public List<SmbmsProvider> getProviderByNCP(int way, List<String> npcs) {
        ProviderMapper providerMapper = sqlSessionTemplate.getMapper(ProviderMapper.class);
        return providerMapper.getProviderByNCP(way,npcs);
    }
}

mapper.xml

<!--    public List<SmbmsProvider> getProviderByNCP(@Param("way") int way, @Param("npc") List<String> npcs);-->
    <select id="getProviderByNCP" resultType="SmbmsProvider">
        select * from smbms_provider
        <choose>
            <when test="way==1">
                where
                <foreach item="npc" index="index" collection="npcs" open="" separator=" or " close="">
                    <if test="npc!=''">
                        proName like concat('%',#{npc},'%')
                    </if>
                </foreach>
            </when>
            <when test="way==2">
                where
                <foreach item="npc" index="index" collection="npcs" open="" separator=" or " close="">
                    <if test="npc!=''">
                        proContact like concat('%',#{npc},'%')
                    </if>
                </foreach>
            </when>
            <when test="way==3">
                where
                <foreach item="npc" index="index" collection="npcs" open="" separator=" or " close="">
                    <if test="npc!=''">
                        proPhone like concat('%',#{npc},'%')
                    </if>
                </foreach>
            </when>
            <otherwise>
                where
                <foreach item="npc" index="index" collection="npcs" open="" separator=" or " close="">
                    <if test="npc!=''">
                        proName like concat('%',#{npc},'%')
                    </if>
                </foreach>
            </otherwise>
        </choose>
        order by `id`
    </select>

經過測試,當List類型參數包含Null時,不會對結果造成影響,因此我上面沒有進行null的判斷,如果你有需求,可以加上

經過測試,當List類型參數包含""(也就是空)的時候,會導致將所有數據都查詢出來了,因此要判斷內容不為空

了解MyBatis foreach標籤相關資訊請查閱:MyBatis foreach標籤 (biancheng.net)

test.java

    ClassPathXmlApplicationContext context= new ClassPathXmlApplicationContext("applicationContext.xml");
    ProviderMapper providerMapper = context.getBean("providerMapperBean",ProviderMapper.class);
    @Test
    public void getProviderByNCPTest(){
        List<String> list1 = new ArrayList<>();
	//下面兩個是我們要查詢的
        list1.add("北京");
        list1.add("深圳");
	//下面這些是用來測試的
        list1.add(null);
        list1.add("");
	//下面這句話是分頁插件的使用,未使用分頁插件則忽略這句話
        Page<Object> page  = PageHelper.startPage(1,3);
	//執行查詢操作
        List<SmbmsProvider> result1 = providerMapper.getProviderByNCP(1,list1);
	//方式1查詢結果合集,通過分頁插件整理了的
        PageInfo<SmbmsProvider> pageInfo1 = new PageInfo<>(result1,3);//三頁
	//輸出相關分頁的資訊
        System.out.println(page);
        System.out.println(pageInfo1);
	//從分頁資訊中取出查詢到的數據
        result1=pageInfo1.getList();
        //格式化輸出
        System.out.println("--------------------根據公司名稱查詢--------------------");
        for(SmbmsProvider smbmsProvider:result1){
            System.out.println(smbmsProvider.getId()+"\t"+smbmsProvider.getProCode()+"\t"+smbmsProvider.getProName()+"\t"+ smbmsProvider.getProContact()+"\t"+smbmsProvider.getProPhone());
        }
    }

【輸出結果如下】

image.png

思路分析

1.最開始,參數沒有使用List,引起的問題

    /**
     * 查詢供應商資訊
     * @param way 查詢方式。1:根據供應商公司名稱模糊查詢 2:根據供應商負責人名字模糊查詢 3:根據電話模糊查詢
     * @param npc 查詢的關鍵字
     * @return List<SmbmsProvider>
     */
     public List<SmbmsProvider> getProviderByNCP(@Param("way") int way, @Param("npc") String npc);

這種方式有一個問題,我查詢「北京」,「深圳」需要分為兩次查詢,後面手動將查詢結果合併在一起,然後又要去考慮id升序排序問題……

正如你所見,很麻煩。尤其是排序問題。因為得到的結果是List,排序要根據List裡面的SmbmsProvider對象裡面的id排序。

如果能一起將多個關鍵字一起查詢,將得到的結果,一個Order By 就解決了,所以,我們要去考慮使用的參數應該是個List,然後裡面包含我們想要查詢的多個關鍵字。

那麼傳入一個List,又怎麼在Mapper.xml中取出想要的東西呢,就發現了後面的 MyBatis foreach

2.Mybatis的foreach

了解MyBatis foreach標籤相關資訊請查閱:MyBatis foreach標籤 (biancheng.net)

3. npc != ''

注意標題上的是兩個單引號,而不是一個雙引號

為什麼我特意用一個 if做判斷?

這裡應對的是List中存在空

1:如果整個列表都空的(也就是一個空列表)

List<String> list1 = new ArrayList<>();
list1.add(null);
list1.add("");

我們沒有在When中進行判斷,列表是否為空,所以它會繼續執行下去

image.png

到達foreach的時候,開始遍歷,如果為空,則後續無語句,若不為空,則繼續添加if塊中的語句

測試當空List傳入時,結果如下

image.png

4.其他

分頁插件在這篇文章並沒有得到充分的應用。