# 菜单路由地址重复问题修复指南 ## 问题描述 在菜单管理中,修改菜单时即使不做任何修改直接点确定,仍然提示"路由地址已存在"。 ## 问题原因 数据库中 `sys_menu` 表存在多条记录使用了相同的 `path` 值,导致校验逻辑误判。 ## 解决步骤 ### 步骤1:查找重复的 path 在数据库中执行以下SQL查询: **PostgreSQL 版本(当前使用):** ```sql -- 查找所有重复的 path SELECT path, COUNT(*) as count, STRING_AGG(CAST(menu_id AS TEXT), ', ') as menu_ids, STRING_AGG(menu_name, ', ') as menu_names FROM sys_menu GROUP BY path HAVING COUNT(*) > 1; ``` **MySQL 版本:** ```sql -- 查找所有重复的 path SELECT path, COUNT(*) as count, GROUP_CONCAT(menu_id) as menu_ids, GROUP_CONCAT(menu_name) as menu_names FROM sys_menu GROUP BY path HAVING COUNT(*) > 1; ``` ### 步骤2:查看具体重复记录的详细信息 将上面的查询结果中的 path 值替换到下面的SQL中: ```sql -- 查看某个重复 path 的详细信息 SELECT * FROM sys_menu WHERE path = 'your_duplicate_path_value' ORDER BY menu_id; ``` ### 步骤3:删除重复记录(保留 menu_id 最小的记录) ```sql DELETE FROM sys_menu WHERE menu_id IN ( SELECT menu_id FROM ( SELECT menu_id, ROW_NUMBER() OVER (PARTITION BY path ORDER BY menu_id) as rn FROM sys_menu ) t WHERE rn > 1 ); ``` ### 步骤4:验证修复结果 ```sql -- 验证是否还有重复的 path SELECT path, COUNT(*) as count FROM sys_menu GROUP BY path HAVING COUNT(*) > 1; ``` 如果没有查询结果,说明重复数据已经清理完毕。 ## 代码修改 ### 已完成的代码修改: 1. **SysMenuMapper.java** - 新增方法 ```java public SysMenu selectMenuByPathExcludeId(@Param("path") String path, @Param("menuId") Long menuId); ``` 2. **SysMenuMapper.xml** - 新增查询 ```xml ``` 3. **SysMenuServiceImpl.java** - 修改校验逻辑 ```java @Override public int updateMenu(SysMenu menu) { //路径Path唯一性判断(排除当前菜单本身) String path = menu.getPath(); if (StringUtils.isNotBlank(path)) { SysMenu sysMenu = menuMapper.selectMenuByPathExcludeId(menu.getPath(), menu.getMenuId()); if (sysMenu != null) { log.warn("路由地址已存在 - menuId: {}, path: {}, 存在的menuId: {}", menu.getMenuId(), menu.getPath(), sysMenu.getMenuId()); return -1; // 路由地址已存在 } } // 执行更新 return menuMapper.updateMenu(menu); } ``` ## 调试信息 当系统提示"路由地址已存在"时,请查看后端日志,会输出类似以下信息: ``` 路由地址已存在 - menuId: 123, path: 'some/path', 存在的menuId: 456 ``` 这可以帮助您快速定位是哪两个菜单发生了冲突。 ## 注意事项 1. 在删除重复记录前,请先备份数据库 2. 建议在测试环境先验证,确认无误后再在生产环境执行 3. 如果某个 path 确实需要被多个菜单使用,需要修改业务逻辑 ## 预防措施 建议在数据库中为 `path` 字段添加唯一索引,从数据库层面防止重复: **PostgreSQL 版本:** ```sql -- 注意:执行前需要先清理重复数据 CREATE UNIQUE INDEX uk_path ON sys_menu(path); ``` **MySQL 版本:** ```sql -- 注意:执行前需要先清理重复数据 ALTER TABLE sys_menu ADD UNIQUE KEY uk_path (path); ```