常州建设网站公司网站,东莞微信网站商城建设,wordpress模板修改字体,湖南搜索引擎推广服务今天要说到的查询情况#xff0c;平时项目里边其实用到的并不是很多#xff0c;使用正则表达式无非是为了匹配结果比较灵活#xff0c;最常见的#xff0c;我们的查询条件一般一个参数仅仅只是一种情况的筛选#xff0c;对于如何选择查询方式#xff0c;主要还是要看前端… 今天要说到的查询情况平时项目里边其实用到的并不是很多使用正则表达式无非是为了匹配结果比较灵活最常见的我们的查询条件一般一个参数仅仅只是一种情况的筛选对于如何选择查询方式主要还是要看前端传递的查询条件格式比如单参数只表示单个值而且数据表对应也是单个值这种最简单精确匹配的话就直接where 字段参数值如果模糊查询就使用like匹配如果前端传递的某个参数值是用逗号分割的一个字符串实际上可以看做是多个匹配条件而数据表中对应的字段值是单个值的话可以where find_in_set(字段,字符串参数值)或者将分割的字符串转换成List然后用in匹配 还有一种就是前端传递的参数值是逗号分割的字符串对应要查询匹配的字段数据表中存的也是以逗号分割的字符串查询的时候一般是或关系就需要从表中查询出只要包含查询条件中的其中一个值的匹配结果 举例来说吧比如昨天一个需求是需要根据标签id来查询只要含有这些标签中其中给一个标签的企业。 先看swagger文档: 这是一个get请求方式的分页查询重点就是下边那个tagIdList参数前端传递的是 一个逗号分割的id字符串是两个标签而企业也是多标签的现在从企业中查询出有这两个标签的企业(其实就是或的关系 接下来看mybatis xml中的sql写法吧 select idpageList resultTypecom.xiaomifeng1010.response.vo.EtpSrvcListedCltvtnVOselectcltvtn.id,SUBSTRING_INDEX(cltvtn.state_record,,,-1) as state,cltvtn.name,(select name from sys_dict where code cltvtn.nature) as nature,(select name from sys_dict where code cltvtn.register_region) as register_region,(select name from sys_dict where code cltvtn.industry) as industry,cltvtn.uscc,cltvtn.master_data_id,cltvtn.wr_tech_type_mid_small_etp,cltvtn.wr_high_new_tech_industry,group_concat(distinct tag.tag_name) as tag_namesfrometp_srvc_listed_cltvtn cltvtnjoin enterprise_info infoon cltvtn.usccinfo.usccleft join enterprise_tag_mid mid on info.idmid.enterprise_idleft join enterprise_tag tag on mid.tag_idtag.idwhere cltvtn.del_flag 0if testparam.name ! null and param.name ! and cltvtn.name like concat(%,#{param.name},%)/ifif testparam.uscc ! null and param.uscc ! and cltvtn.uscc like concat(%,#{param.uscc},%)/ifif testparam.nature ! nulland cltvtn.nature #{param.nature}/ifif testparam.registerRegion ! null and param.registerRegion ! and cltvtn.register_region #{param.registerRegion}/ifif testparam.state!nulland SUBSTRING_INDEX(cltvtn.state_record,,,-1)#{param.state,jdbcTypeINTEGER}/ifgroup by cltvtn.name,cltvtn.usccif testparam.tagIdList ! null and param.tagIdList.size() ! 0HAVING group_concat(distinct tag.id) REGEXPreplace(foreach collectionparam.tagIdList itemtagId separator| openconcat(close)#{tagId,jdbcTypeBIGINT}/foreach, ,)/ifif testparam.sort ! and param.sort ! nullorder by ${param.sort}/ifif testparam.sort or param.sort nullorder by cltvtn.create_time desc/if/select 要匹配标签或关系 我一开始是这样写的为什么这样写的因为以前我使用Integer类型的枚举值List时候这样用是可以正常匹配的所以Id值是Long类型的依然这样用但是结果查询结果出乎我的预料当我选择单个标签或者不选标签的时候是可以正常查询结果的但是当我选择的是两个标签时候奇怪的事情就发生了居然一条结果都没有了像下边这样 我选单个标签的时候是可以查询出231条结果的
但是当我选择两个标签的时候居然一条结果都没有 正常情况下foreach拼接的tagId拼接好完整的sql应该是这样的 我在navicat中直接执行这个语句是可以正常查询到结果的但是在程序中就是没有查询结果所以我又去试了一下测试环境并查看日志并且我把#{tagId}换成了${tagId}方便直接打印sql的时候直接带上参数而不是占位符看到的日志信息就是这样的 可以看到使用concat拼接的正则表达式每个id以及‘|’符号之间都加上了空格应该是mybatis加上的所以为了去掉空格所以我又加上了replace函数然后在本地测试结果本地可以查询出来一些结果了但是结果却是只有匹配第二个标签的结果好家伙replace没有替换掉‘|’符号前边那个id的空格然后发到测试环境结果测试环境还是查不到结果就非常诡异正常情况下replace是可以替换掉字符串中所有空格的在Navicat中运行也是正常的 既然mybatis会改变最终的拼接结果那么索性不用mybatis来拼接了解决方案是使用ognl表达式直接用java的api就可以了所以最终改写成了
select idpageList resultTypecom.xiaomifeng1010.response.vo.EtpSrvcListedCltvtnVOselectcltvtn.id,SUBSTRING_INDEX(cltvtn.state_record,,,-1) as state,cltvtn.name,(select name from sys_dict where code cltvtn.nature) as nature,(select name from sys_dict where code cltvtn.register_region) as register_region,(select name from sys_dict where code cltvtn.industry) as industry,cltvtn.uscc,cltvtn.master_data_id,cltvtn.wr_tech_type_mid_small_etp,cltvtn.wr_high_new_tech_industry,group_concat(distinct tag.tag_name) as tag_namesfrometp_srvc_listed_cltvtn cltvtnjoin enterprise_info infoon cltvtn.usccinfo.usccleft join enterprise_tag_mid mid on info.idmid.enterprise_idleft join enterprise_tag tag on mid.tag_idtag.idwhere cltvtn.del_flag 0if testparam.name ! null and param.name ! and cltvtn.name like concat(%,#{param.name},%)/ifif testparam.uscc ! null and param.uscc ! and cltvtn.uscc like concat(%,#{param.uscc},%)/ifif testparam.nature ! nulland cltvtn.nature #{param.nature}/ifif testparam.registerRegion ! null and param.registerRegion ! and cltvtn.register_region #{param.registerRegion}/ifif testparam.state!nulland SUBSTRING_INDEX(cltvtn.state_record,,,-1)#{param.state,jdbcTypeINTEGER}/ifgroup by cltvtn.name,cltvtn.usccif testparam.tagIdList ! null and param.tagIdList.size() ! 0bind namejoiner valuecom.google.common.base.Joineron(|)/bind nametagIds valuejoiner.join(param.tagIdList)/HAVING group_concat(distinct tag.id) REGEXP#{tagIds}/ifif testparam.sort ! and param.sort ! nullorder by ${param.sort}/ifif testparam.sort or param.sort nullorder by cltvtn.create_time desc/if/select
然后再到swagger文档中测试,就可以正常查询到准确的结果条数了 但是如果是Integer类型的枚举值列表使用foreach来拼接正则表达式目前测试是可以正常查询的比如另外一个查询场景之前的一个业务在新增金融政策的时候 政策类型下拉选只能单选所以设计的数据表字段直接是枚举int类型1,2,3来存储的后来要求这个字段可以下拉多选所以就改成了字符串类型多选的时候传递过来的参数值就类似‘1,2,3’这样逗号拼接的字符串存储到该字段中同时查询也由单选改成了多选
所以查询也要改写成这样
select idpageList resultTypecom.xiaomifeng1010.response.vo.FinancePolicyVOselectfp.id,fp.title,fp.publish_date,fp.content,fp.publish_office,fp.written_date,fp.typefrom finance_policy fpwhere fp.del_flag 0if testparam.title ! and param.title ! nulland fp.title like concat(%,#{param.title},%)/ifif testparam.supportType ! and param.supportType ! nulland fp.support_type like concat(%,#{param.supportType},%)/ifif testparam.supportMode ! and param.supportMode ! nulland fp.support_mode like concat(%,#{param.supportMode},%)/ifif testorg.apache.commons.lang3.StringUtilsisNotBlank(param.type)and fp.type like concat(%,#{param.type},%)/ifif testorg.apache.commons.collections4.CollectionUtilsisNotEmpty(param.typeList)and fp.type REGEXPforeach collectionparam.typeList openconcat( itemtype close) separator|#{type,jdbcTypeINTEGER}/foreach/ifif testparam.dateRange ! nulland fp.publish_date subdate(CURRENT_DATE,#{param.dateRange})/ifif testparam.sort ! and param.sort ! nullorder by ${param.sort}/ifif testparam.sort or param.sort nullorder by fp.publish_date desc/if/select注意这里拼接的是integer类型的值 没有出现查询不到结果的情况当前端选择两种政策类型时只要包含这两种类型的一种都会查询出来 可以看到type是2或者3的都可以查出来以及同时是2,3的也可以查出来
最后再说明一下其他注意事项
如果要在foreach中使用#{item}的形式那么open和close的值不能直接是单引号因为#参数值两边不能直接是单引号open值可以是concat(,close的值是)这样的如果要用单引号也不是不可以将#换成$就可以了 另外还有一种就是匹配英文字符串或者中文的那种情况比如查询某字段包含某个编码或另一个编码以及某字段是否包含某段文字或其他文字之类的也可以使用全文索引需要对查询字段创建全文索引并且查询语句使用match against形式查询语句具体的匹配模式可以查询相关资料 不过全文索引创建的字段只对新添加或更新的行数据生效也就是说即使旧数据满足匹配条件也查询不出来所以可以做全表更新或者旧数据清除处理之后再用全文索引匹配