情景分析
题目
现在我们要执行查询操作,例如我要查询商品的供应商信息。供应商的信息包括公司名称,负责人名字,联系电话,公司地址等。
我也许会输入电话号码的前几位查询,也许会输入公司名称的某个字查询,也许会输出负责人的姓氏查询……
我希望查出来的结果,是按照Id升序排序好了的。
要求
1.我要根据公司名称查询,只要公司名称包含“广东”、“深圳”的都可以被查询出来
2.我要根据负责人名字查询,只要负责人名字包含“周”、“吴”、“郑”、“王”的都可以被查询出来
3.我要根据电话号码查询,只要电话号码包含“139”,“136”,“137”的都可以被查询出来
相关代码
下面MyBatis的配置方式是Spring整合MyBatis的,详情请参阅下面这篇文章
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()); } }
【输出结果如下】
思路分析
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
中进行判断,列表是否为空,所以它会继续执行下去
到达foreach
的时候,开始遍历,如果为空,则后续无语句,若不为空,则继续添加if
块中的语句
测试当空List传入时,结果如下
4.其他
分页插件在这篇文章并没有得到充分的应用。