问题描述:
源代码只有单一条件,即只需输入一个人名进行查找并返回结果即可,因此,只需要动态Sql同时使用like关键字,使用concat函数将%与动态数据拼接即可实现模糊查找功能。
仔细观察,这里的匹配为两种方式的匹配,即是否and该column取决于login_id或name的匹配,若两者之一满足条件(使用or关键字),那种这个数据就会最后显示出来,这一点也为我们后续的实现增加了难度。
<!-- 原始查询 --> <if test="subscribeName.length != 0 and subscribeName!=null and subscribeName != 'null'"> AND (IFNULL(s.login_id,'') LIKE CONCAT('%',#{subscribeName},'%') OR IFNULL(l.name,'') LIKE CONCAT('%',#{subscribeName},'%')) </if>
原因分析:
首先我们从数据输入着手,观察接口可知原本为String类型的subscribeName,当多订阅人输入时,就变成了一个内部带英文逗号分隔的长字符串。为了保证可读性我们仍在xml文件中的sql语句修改。
要实现所有姓名的依次匹配,使用foreach进行一个遍历,遍历的数据来源为在foreach头部使用spilit将subscribeName分隔的数组。
在姓名分割时需要注意的是,如果用户错误输入了些空字段,要求我们具有健壮性依然能返回想要的结果,大致思想是replace方法或者trim方法,但实际上trim更优,我们后文讨论
解决方案:
方案一:foreach+in
在foreach中使用in来精准匹配,这是最开始想到的方法。虽然丧失了模糊查找的功能,但是这种方法最直观也容易理解,网上的资料也大多是使用in关键字。这种方法下我们使用两个foreach分别服务login_id和name。
<!-- 使用in的查询 --> <if test="subscribeName!='' and subscribeName!=null and subscribeName != 'null'"> and IFNULL(s.login_id,'') in <foreach collection="subscribeName.split(',')" item="subscribeName" separator="," open="(" close=")"> #{subscribeName} </foreach> or IFNULL(l.name,'') in <foreach collection="subscribeName.split(',')" item="subscribeName" separator="," open="(" close=")"> #{subscribeName} </foreach> </if>
方案二: foreach+like+replaceAll
在每一轮遍历中,仍然使用concat拼接,进行模糊查找,使用两个foreach服务两个匹配方法,但不同之处在于foreach体的separator此时为or。
同时,我们在spilit分割前使用replaceAll将字符串中的所有空格去除掉
<!-- foreach内模糊查询like,同时使用replace除去所有空字段 --> <if test="subscribeName!='' and subscribeName!=null and subscribeName != 'null'"> AND (IFNULL(s.login_id,'') LIKE <foreach collection="subscribeName.replaceAll('[\\[\\] ]','').split(',')" open="(" separator="or" close=")" item="subscribeName"> CONCAT('%',#{subscribeName},'%') </foreach> OR (IFNULL(l.name,'')) LIKE <foreach collection="subscribeName.replaceAll('[\\[\\] ]','').split(',')" open="(" separator="or" close=")" item="subscribeName"> CONCAT('%',#{subscribeName},'%')) </foreach> </if>
方案三:foreach+like+trim
仔细想想,其实方案二的replaceAll存在不足之处,那就是我们在测试时往往只用随便随便起的名字,而实际上如果真的有外文名输入,那么空格若被一并去除,就会造成难以阅读的现象。
改进方法就是在每一轮foreach,使用trim将字段的首尾空格去掉即可。
<!-- 要在foreach语句里面使用trim --> <if test="subscribeName!='' and subscribeName!=null and subscribeName != 'null'"> AND (IFNULL(s.login_id,'') LIKE <foreach collection="subscribeName.split(',')" open="(" separator="or" close=")" item="subscribeName"> CONCAT('%',trim(#{subscribeName}),'%') </foreach> OR (IFNULL(l.name,'')) LIKE <foreach collection="subscribeName.split(',')" open="(" separator="or" close=")" item="subscribeName"> CONCAT('%',trim(#{subscribeName}),'%')) </foreach> </if>
场景描述:
分页查询:复选框传多个查询条件,数据库字段说逗号拼接的 这种场景。
标签:name,IFNULL,数据库,逗号,拼接,subscribeName,foreach,login,LIKE From: https://www.cnblogs.com/zhihongming/p/16745828.html