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实现递归删除?