优化分类树加载逻辑,新增批量查询子节点接口以减少数据库往返,提升性能。重构相关服务和控制器,确保系统的可维护性和扩展性。

This commit is contained in:
geht
2026-05-15 09:58:30 +08:00
parent bc1de2c765
commit ffc390f3de
8 changed files with 85 additions and 13 deletions

View File

@@ -416,13 +416,7 @@ public class SysCategoryController {
* 递归求子节点 同步加载用到
*/
private void loadAllCategoryChildren(List<TreeSelectModel> ls) {
for (TreeSelectModel tsm : ls) {
List<TreeSelectModel> temp = this.sysCategoryService.queryListByPid(tsm.getKey());
if(temp!=null && temp.size()>0) {
tsm.setChildren(temp);
loadAllCategoryChildren(temp);
}
}
this.sysCategoryService.fillCategoryChildrenBatch(ls);
}
/**

View File

@@ -28,6 +28,11 @@ public interface SysCategoryMapper extends BaseMapper<SysCategory> {
*/
public List<TreeSelectModel> queryListByPid(@Param("pid") String pid,@Param("query") Map<String, String> query);
/**
* 批量按父 id 查询子节点(树同步加载按层拉取,避免 N+1
*/
List<TreeSelectModel> queryListByPidIn(@Param("pids") List<String> pids, @Param("query") Map<String, String> query);
/**
* 通过code查询分类字典表
* @param code

View File

@@ -33,5 +33,36 @@
</if>
</select>
<select id="queryListByPidIn" resultType="org.jeecg.modules.system.model.TreeSelectModel">
select code,
name as "title",
id as "key",
(case when has_child = '1' then 0 else 1 end) as isLeaf,
pid as parentId
from sys_category
where pid in
<foreach collection="pids" item="item" open="(" separator="," close=")">
#{item}
</foreach>
<if test="query!= null">
<if test="query.code !=null and query.code != ''">
and code = #{query.code}
</if>
<if test="query.name !=null and query.name != ''">
and name = #{query.name}
</if>
<if test="query.id !=null and query.id != ''">
and id = #{query.id}
</if>
<if test="query.createBy !=null and query.createBy != ''">
and create_by = #{query.createBy}
</if>
<if test="query.sysOrgCode !=null and query.sysOrgCode != ''">
and sys_org_code = #{query.sysOrgCode}
</if>
</if>
order by code
</select>
</mapper>

View File

@@ -98,4 +98,11 @@ public interface ISysCategoryService extends IService<SysCategory> {
*/
List<String> loadDictItemByNames(String names, boolean delNotExist);
/**
* 按层批量补全子节点(替代逐节点递归 queryListByPid显著减少数据库往返
*
* @param nodes 首层节点列表(通常来自 {@link #queryListByCode}
*/
void fillCategoryChildrenBatch(List<TreeSelectModel> nodes);
}

View File

@@ -126,6 +126,37 @@ public class SysCategoryServiceImpl extends ServiceImpl<SysCategoryMapper, SysCa
return baseMapper.queryListByPid(pid,condition);
}
@Override
public void fillCategoryChildrenBatch(List<TreeSelectModel> nodes) {
if (nodes == null || nodes.isEmpty()) {
return;
}
List<TreeSelectModel> frontier = new ArrayList<>(nodes);
while (!frontier.isEmpty()) {
List<String> pids = frontier.stream().map(TreeSelectModel::getKey).filter(Objects::nonNull).collect(Collectors.toList());
if (pids.isEmpty()) {
break;
}
List<TreeSelectModel> allChildren = baseMapper.queryListByPidIn(pids, null);
if (allChildren == null || allChildren.isEmpty()) {
break;
}
Map<String, List<TreeSelectModel>> byParent = allChildren.stream().collect(Collectors.groupingBy(TreeSelectModel::getParentId));
List<TreeSelectModel> nextFrontier = new ArrayList<>();
for (TreeSelectModel parent : frontier) {
List<TreeSelectModel> ch = byParent.get(parent.getKey());
if (ch != null && !ch.isEmpty()) {
parent.setChildren(ch);
nextFrontier.addAll(ch);
}
}
if (nextFrontier.isEmpty()) {
break;
}
frontier = nextFrontier;
}
}
@Override
public String queryIdByCode(String code) {
return baseMapper.queryIdByCode(code);