迁移:将DB变更记录SQL文件移动到sql目录下
This commit is contained in:
140
sql/迁移记录-DB变更记录/菜单路由地址重复问题修复指南.md
Normal file
140
sql/迁移记录-DB变更记录/菜单路由地址重复问题修复指南.md
Normal file
@@ -0,0 +1,140 @@
|
||||
# 菜单路由地址重复问题修复指南
|
||||
|
||||
## 问题描述
|
||||
在菜单管理中,修改菜单时即使不做任何修改直接点确定,仍然提示"路由地址已存在"。
|
||||
|
||||
## 问题原因
|
||||
数据库中 `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
|
||||
<select id="selectMenuByPathExcludeId" resultMap="SysMenuResult">
|
||||
<include refid="selectMenuVo"/>
|
||||
where path = #{path} and menu_id != #{menuId}
|
||||
</select>
|
||||
```
|
||||
|
||||
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);
|
||||
```
|
||||
Reference in New Issue
Block a user