【MyBatis】多关键字的模糊查询

任务驱动才能明确方向。我举一个例子。

情景分析

题目

现在我们要执行查询操作,例如我要查询商品的供应商信息。供应商的信息包括公司名称,负责人名字,联系电话,公司地址等。

我也许会输入电话号码的前几位查询,也许会输入公司名称的某个字查询,也许会输出负责人的姓氏查询……

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

要求

1.我要根据公司名称查询,只要公司名称包含“广东”、“深圳”的都可以被查询出来

2.我要根据负责人名字查询,只要负责人名字包含“周”、“吴”、“郑”、“王”的都可以被查询出来

3.我要根据电话号码查询,只要电话号码包含“139”,“136”,“137”的都可以被查询出来

相关代码

下面MyBatis的配置方式是Spring整合MyBatis的,详情请参阅下面这篇文章

【Spring】【MyBatis】Spring整合MyBatis01 - 萌狼蓝天 - 博客园 (https://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.其他

分页插件在这篇文章并没有得到充分的应用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

萌狼蓝天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值