在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中多表查询的灵活别名筛选,避免字段歧义问题。该方法适用于复杂报表场景,建议根据实际业务增强判断逻辑。希望这个分享对你有帮助!