jeecgboot mapper.xml联合查询之前端灵活使用表别名筛选

warning: 这篇文章距离上次修改已过492天,其中的内容可能已经有所变动。

# jeecgboot mapper.xml联合查询之前端灵活使用表别名筛选

一、背景

一个项目使用jeecgboot来进行开发,有一个需求:报表里的关键字段都能在前端做查询筛选。由于这个报表是通过mapper.xml 里写sql然后动态拼接的,很多关键字段在不同的表里,如果前端直接传name=xxx,将会报错:Column 'name' in where clause is ambiguous,大概意思是表字段不明确。又或者我只想查老师级别level=1下的学生时,直接传level=1,也同样会报错。

-- 这个是举例说明,实际业务比这复杂得多
select a.name,b.sex,c.name,c.level tName from students a 
left join sexs b on a.sexId=b.sexId 
inner join teachers c on a.tId=c.id
${ew.customSqlSegment} 

二、分析

解决思路比较简单,要确保${ew.customSqlSegment}里拼接的where条件,带上对应的别名。但jeecgboot默认不支持传别名字段,怎么办呢?经过分析前后端源码,解决步骤大概如下:

  1. 重写getQueryParams
    前端重写getQueryParams,var params = this.getQueryParams() 在params参数里对需要明确别名的字段加上别名。
  2. 后端改queryWrapper

    QueryGenerator---installMplus里增加对别名字段的处理,让它拼接成需要的where查询。

三、具体代码

  1. 前端

    ==注意必须delete ,否则旧的参数也会提交过去,导致后端没法明确字段而报错==

     getQueryParams(){//重写查询
           。。。。。。。
          var params=  filterObj(param);
        
          if(params.level)
          {
            params['c.level']=params.level
            delete params.level
          }
          if(params.name){
             params['c.name']=params.name
            delete params.name
          }
      
           return params;
        }
  2. 后端
    QueryGenerator的installMplus里增加。注意是在else里加上,因为比如要查level,前端传来c.level,在searchObj里不存在(==level=null==),所以不会去查值,导致value必然为null。然后对过request中的parameterMap判断是否有带别名的字段,去掉别名后如果与当前字段相同,则认为需要手动加别名。将原来的key换成新别名。column=key并将查询内容赋值给 value=String.join(",",parameterMap.get(key));

        public static void installMplus(QueryWrapper<?> queryWrapper, Object searchObj, Map<String, String[]> parameterMap) {
            。。。。。
        if (null != value && value.toString().startsWith(COMMA) && value.toString().endsWith(COMMA)) {
                。。。。。。
        }else {
    //如果值为空,有可能是前端给了别名,此时应该去别名后再匹配实体字段,相同则从reqMap里取值。
                        if(null==value && parameterMap!=null){
                            String finalColumn = column;
                            String key=  parameterMap.keySet().stream().filter(x->( x.contains(".") && x.contains(finalColumn))).findFirst().orElse(null);
                            if(key!=null){
                                column=key;
                                 //这里是前端传来的要查询的内容  ['xx','xxx2']
                                value=String.join(",",parameterMap.get(key));
                            }
                        }
                        //根据参数值带什么关键字符串判断走什么类型的查询
                        QueryRuleEnum rule = convert2Rule(value);
             。。。。。
         }
        }

    当然,上面的判断其实是不严谨的,可以自己想办法增强!

none
最后修改于:2023年07月20日 11:53

评论已关闭