Spring Boot 菜单删除实现代码与事务管理

 更新时间:2025年08月13日 10:19:51   作者:小白的代码日记  
本文将详细介绍Spring Boot环境下菜单删除功能的实现逻辑,包括关联数据处理、事务控制和异常处理等关键环节,强调需处理多级嵌套、角色关联及数据一致性,感兴趣的朋友跟随小编一起看看吧

在后台管理系统开发中,菜单管理是一个核心功能,而删除菜单作为其中的重要操作,需要考虑数据完整性、关联关系处理和操作安全性。本文将详细介绍 Spring Boot 环境下菜单删除功能的实现逻辑,包括关联数据处理、事务控制和异常处理等关键环节。

菜单删除的业务逻辑分析

菜单删除并非简单地删除一条记录,需要考虑以下几点:

  • 菜单可能存在多级嵌套关系(父菜单与子菜单)
  • 菜单与角色存在多对多关联(通过中间表 role_menu)
  • 操作需要具备原子性(要么全部成功,要么全部失败)

因此,完整的菜单删除逻辑应该是:先删除关联数据,再删除子菜单,最后删除父菜单本身,并通过事务保证整个过程的完整性。

实现代码与步骤解析

1. 控制器层(MenuController)

首先定义删除接口,接收菜单 ID 并添加事务注解:

@RestController
@RequestMapping("/menu")
public class MenuController {
    @Autowired
    private MenuService menuService;
    @Autowired
    private RoleMenuMapper roleMenuMapper;
    /**
     * 删除菜单
     * @param id 菜单ID
     * @return 操作结果
     */
    @DeleteMapping("/del/{id}")
    @Transactional  // 事务注解,确保操作原子性
    public Result deleteMenu(@PathVariable Integer id) {
        try {
            // 1. 查询所有子菜单
            QueryWrapper<MenuEntity> subMenuQuery = new QueryWrapper<>();
            subMenuQuery.eq("parent_id", id);
            List<MenuEntity> subMenus = menuService.list(subMenuQuery);
            // 2. 先删除子菜单与角色的关联关系
            if (!subMenus.isEmpty()) {
                for (MenuEntity subMenu : subMenus) {
                    QueryWrapper<RoleMenuEntity> roleMenuQuery = new QueryWrapper<>();
                    roleMenuQuery.eq("menu_id", subMenu.getMenuId());
                    roleMenuMapper.delete(roleMenuQuery);
                }
                // 3. 删除子菜单
                menuService.remove(subMenuQuery);
            }
            // 4. 删除当前菜单与角色的关联关系
            QueryWrapper<RoleMenuEntity> parentRoleMenuQuery = new QueryWrapper<>();
            parentRoleMenuQuery.eq("menu_id", id);
            roleMenuMapper.delete(parentRoleMenuQuery);
            // 5. 删除当前菜单
            boolean isDeleted = menuService.removeById(id);
            if (isDeleted) {
                return Result.success("菜单删除成功");
            } else {
                return Result.error("菜单不存在或已被删除");
            }
        } catch (Exception e) {
            // 抛出运行时异常,触发事务回滚
            throw new RuntimeException("删除菜单失败:" + e.getMessage());
        }
    }
}

2. 关键步骤解析

步骤 1:查询子菜单

通过 parent_id 查询当前菜单的所有子菜单,为后续级联删除做准备:

QueryWrapper<MenuEntity> subMenuQuery = new QueryWrapper<>();
subMenuQuery.eq("parent_id", id);
List<MenuEntity> subMenus = menuService.list(subMenuQuery);

步骤 2:删除子菜单与角色的关联关系

由于菜单与角色通过中间表 role_menu 关联,需要先删除这些关联数据,避免外键约束错误:

for (MenuEntity subMenu : subMenus) {
    QueryWrapper<RoleMenuEntity> roleMenuQuery = new QueryWrapper<>();
    roleMenuQuery.eq("menu_id", subMenu.getMenuId());
    roleMenuMapper.delete(roleMenuQuery);
}

步骤 3:删除子菜单

在删除关联数据后,批量删除所有子菜单:

menuService.remove(subMenuQuery);

步骤 4:删除当前菜单与角色的关联关系

同样需要解除当前菜单与角色的关联:

QueryWrapper<RoleMenuEntity> parentRoleMenuQuery = new QueryWrapper<>();
parentRoleMenuQuery.eq("menu_id", id);
roleMenuMapper.delete(parentRoleMenuQuery);

步骤 5:删除当前菜单

最后删除主菜单记录:

menuService.removeById(id);

事务管理与异常处理

  • 事务保证:通过@Transactional注解,确保整个删除过程的原子性。如果任何步骤失败,所有操作都会回滚,避免数据不一致。
  • 异常处理
    • 使用 try-catch 块捕获可能的异常
    • 抛出RuntimeException触发事务回滚(符合 Spring 事务默认回滚规则)
    • 提供清晰的错误信息,便于问题排查
  • 删除顺序原则
    • 先删关联数据,再删主数据
    • 先删子菜单,再删父菜单
    • 遵循 "从外向内、从下到上" 的删除顺序,避免外键约束冲突

到此这篇关于Spring Boot 菜单删除功能的实现与事务管理的文章就介绍到这了,更多相关Spring Boot 菜单删除内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 为何Java8需要引入新的日期与时间库

    为何Java8需要引入新的日期与时间库

    这篇文章主要给大家介绍了关于Java8为什么需要引入新的日期与时间库的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • 基于SpringBoot框架实现文件上传下载分享功能

    基于SpringBoot框架实现文件上传下载分享功能

    在当今的Web应用开发中,文件上传与下载功能是极为常见且重要的需求,无论是用户上传头像、分享文档,还是系统生成报告供用户下载,都离不开这一功能模块,SpringBoot作为一款流行的Java开发框架,为我们提供了简洁高效的方式来实现文件上传与下载,需要的朋友可以参考下
    2025-06-06
  • Java内存模型JMM详解

    Java内存模型JMM详解

    这篇文章主要介绍了Java内存模型JMM详解,涉及volatile和监视器锁,final字段,内存屏障等相关内容,具有一定参考价值,需要的朋友可以了解下。
    2017-11-11
  • mybatisplus如何实现排序

    mybatisplus如何实现排序

    这篇文章主要介绍了mybatisplus如何实现排序问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-02-02
  • SpringBoot+Redis队列实现Java版秒杀的示例代码

    SpringBoot+Redis队列实现Java版秒杀的示例代码

    本文主要介绍了SpringBoot+Redis队列实现Java版秒杀的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-06-06
  • java8新特性-lambda表达式入门学习心得

    java8新特性-lambda表达式入门学习心得

    这篇文章主要介绍了java8新特性-lambda表达式入门学习心得,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • java线程池详解及代码介绍

    java线程池详解及代码介绍

    这篇文章主要介绍了java中线程池的示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-08-08
  • Java获取指定父节点、子节点的方法实现

    Java获取指定父节点、子节点的方法实现

    在Java中,要获取指定节点的父节点和子节点,通常需要使用 DOM,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧
    2024-02-02
  • kotlin和Java的相互调用示例详解

    kotlin和Java的相互调用示例详解

    Kotlin 的设计过程中就考虑到了与 Java 的互操作性。在 Kotlin 中可以直接调用既有的 Java 代码, 反过来在 Java 中也可以很流畅地使用 Kotlin 代码,下面这篇文章主要给大家介绍了关于kotlin和Java的相互调用的相关资料,需要的朋友可以参考下。
    2018-02-02
  • java正则表达式学习笔记之命名捕获

    java正则表达式学习笔记之命名捕获

    这篇文章主要为大家详细介绍了java正则表达式中的命名捕获,感兴趣的小伙伴们可以参考一下
    2016-02-02

最新评论