在JeecgBoot开发中,使用Mapper.xml编写SQL进行动态拼接的报表查询时,前端筛选可能因多表同名字段导致报错(如Column 'name' in where clause is ambiguous)。本文分享如何通过前后端修改实现灵活的表别名筛选。
项目需求:报表关键字段支持前端查询筛选。这些字段分布在不同表中,直接传递参数(如name=xxx或level=1)会因字段歧义报错。示例SQL如下(实际业务更复杂):
-- 示例SQL SELECT a.name, b.sex, c.name, c.level AS tName FROM students a LEFT JOIN sexs b ON a.sexId = b.sexId INNER JOIN teachers c ON a.tId = c.id ${ew.customSqlSegment}
核心思路:确保动态拼接的WHERE条件带上表别名。JeecgBoot默认不支持别名参数传递,因此需修改前后端代码:
前端:重写getQueryParams方法,为需要别名的字段添加前缀(如c.level),并删除原参数。
后端:修改QueryGenerator的installMplus方法,处理带别名的参数,动态调整查询条件。
重写getQueryParams方法,添加别名并删除原参数,以避免后端歧义报错:
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; }
在QueryGenerator的installMplus方法中,处理带别名的参数:当value为空时,从parameterMap中查找匹配的带点键值,调整column和value:
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); // ... 其他代码 ... } }
注意:上述判断逻辑可进一步优化以提高严谨性。
通过前后端协作修改,可实现JeecgBoot中多表查询的灵活别名筛选,避免字段歧义问题。该方法适用于复杂报表场景,建议根据实际业务增强判断逻辑。希望这个分享对你有帮助!