Files
his/sql/迁移记录-DB变更记录/菜单路由地址重复问题修复指南.md

3.6 KiB
Raw Blame History

菜单路由地址重复问题修复指南

问题描述

在菜单管理中,修改菜单时即使不做任何修改直接点确定,仍然提示"路由地址已存在"。

问题原因

数据库中 sys_menu 表存在多条记录使用了相同的 path 值,导致校验逻辑误判。

解决步骤

步骤1查找重复的 path

在数据库中执行以下SQL查询

PostgreSQL 版本(当前使用):

-- 查找所有重复的 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 版本:

-- 查找所有重复的 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中

-- 查看某个重复 path 的详细信息
SELECT * FROM sys_menu
WHERE path = 'your_duplicate_path_value'
ORDER BY menu_id;

步骤3删除重复记录保留 menu_id 最小的记录)

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验证修复结果

-- 验证是否还有重复的 path
SELECT
    path,
    COUNT(*) as count
FROM sys_menu
GROUP BY path
HAVING COUNT(*) > 1;

如果没有查询结果,说明重复数据已经清理完毕。

代码修改

已完成的代码修改:

  1. SysMenuMapper.java - 新增方法
public SysMenu selectMenuByPathExcludeId(@Param("path") String path, @Param("menuId") Long menuId);
  1. SysMenuMapper.xml - 新增查询
<select id="selectMenuByPathExcludeId" resultMap="SysMenuResult">
    <include refid="selectMenuVo"/>
    where path = #{path} and menu_id != #{menuId}
</select>
  1. SysMenuServiceImpl.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 版本:

-- 注意:执行前需要先清理重复数据
CREATE UNIQUE INDEX uk_path ON sys_menu(path);

MySQL 版本:

-- 注意:执行前需要先清理重复数据
ALTER TABLE sys_menu ADD UNIQUE KEY uk_path (path);