练习:递归删除树形结构

本文探讨了如何在服务层(service)和Mapper.xml中实现递归删除树形结构的简单方法,以及遇到的挑战,如处理根节点和叶子节点的特殊情况。文章还提出,当数据量增大时,一次性加载所有菜单信息可能导致效率问题,并引发对使用SQL实现递归删除的思考。
摘要由CSDN通过智能技术生成

service:

@Service
public class SysMenuServiceImpl implements SysMenuService {
    @Autowired
    private SysMenuDao sysMenuDao;
    @Autowired
    private SysMenuRoleDao sysMenuRoleDao;

    @Override
    public JsonResult findObjects() {
        List<Map<String, Object>> list = sysMenuDao.findObjects();
        return new JsonResult(list);
    }

    @Override
    @Transactional
    public int deleteObject(Long id) {
        List<SysMenu> childMenus = findChildMenus(id);
        sysMenuRoleDao.deleteObjectsByMenuId(childMenus);
        sysMenuDao.deleteObjectsById(childMenus);
        return 0;
    }

    @Override
    public int getChildCount(Long id) {
        return 0;
    }

    @Override
    public List<SysMenu> findAllMenuIdAndParentId() {
        return sysMenuDao.findAllMenuIdAndParentId();
    }

    @Override
    public List<SysMenu> findChildMenus(Long id) {
        List<SysMenu> menuList = findAllMenuIdAndParentId();
        return getChild(id, menuList);
    }

    /**
     * 递归获取子节点id和parentId 封装成List<SysMenu>集合
     * @param id    菜单id
     * @param menuIds   一次查询出的所有菜单数据
     * @return  子节点菜单集合
     */
    @Override
    public List<SysMenu> getChild(Long id, List<SysMenu> menuIds) {
        List<SysMenu> childMenus = new ArrayList<>();
        for (SysMenu menu :
                menuIds) {
            if (menu.getParentId()==null&& menu.getId().equals(id)){
                childMenus.add(menu);
                continue;
            }else if (menu.getParentId()==null){
                continue;
            }
            //根目录的parentId为null
            if (menu.getParentId().equals(id)) {
                childMenus.add(menu);
                List<SysMenu> child = getChild(menu.getId(), menuIds);
                //addAll将List中所有集加入到另一个List中
                childMenus.addAll(child);
            }
        }
        SysMenu currentMenu = sysMenuDao.selectOneById(id);
        //判断是否为叶子节点,是的话需手动加入
        if (childMenus.size()==0){
            childMenus.add(currentMenu);
        }else if (currentMenu.getParentId()!=null){ //判断是否为根节点,不是根节点需要手动加入到菜单集合中
            childMenus.add(currentMenu);
        }
        return childMenus;
    }

}

mapper.xml:

SysMenuMapper.xml

<mapper namespace="com.cy.pj.sys.dao.SysMenuDao">
    <select id="findObjects" resultType="map">
        /*方案一: 嵌套查询*/
        /*select c.*,
               (select p.name
                from sys_menus p
                where c.parentId = p.id) parantName
        from sys_menus c*/
        /*方案二: 多表左外关联查询
          左外关联: 左边满足条件和不满足条件的都要显示
          右边表不满足条件的线时null*/
        select c.*, p.name parentName
        from sys_menus c
                 left join sys_menus p on c.parentId = p.id
    </select>

    <select id="findAllMenuIdAndParentId" resultType="com.cy.pj.sys.entity.SysMenu">
        select id, parentId
        from sys_menus
    </select>

    <delete id="deleteObjectsById" parameterType="com.cy.pj.sys.entity.SysMenu">
        delete from sys_menus
        where id in
        <foreach collection="menus"
                 item="menu"
                 open="("
                 close=")"
                 separator=",">
            #{menu.id}
        </foreach>
    </delete>

    <delete id="deleteAll">
        delete
        from sys_menus;
    </delete>

    <select id="selectOneById" resultType="com.cy.pj.sys.entity.SysMenu">
        select id, parentId
        from sys_menus
        where id = #{id}
    </select>
</mapper>

SysRoleMenuMapper.xml

<mapper namespace="com.cy.pj.sys.dao.SysMenuRoleDao">
    <delete id="deleteObjectsByMenuId" parameterType="com.cy.pj.sys.entity.SysMenu">
        delete from sys_role_menus where menu_id in
        <foreach collection="menuIds" item="menu"
                 open="("
                 close=")"
                 separator=",">
                #{menu.id}
        </foreach>
    </delete>

    <delete id="deleteAll">
        delete from sys_role_menus;
    </delete>
</mapper>

简单的递归删除:

采用的是一次性查询出所有的菜单信息,然后再遍历筛选出符合条件的节点添加到List集合中。
遇到的问题:
需要注意查询到的数据的值,根节点没有父节点,设置的值可能为null,需要加以判断。
当前节点(不是根节点),或者查询的是叶子节点都需要判断手动添加进集合中。

拓展:

  • 每一次遍历的list集合都是所有的menu信息,当数据量大时,应该怎么做?
  • 怎么用sql实现递归删除?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值