递归获取树形结构数据(地区数据)

本文介绍了如何使用Spring Boot和MapStruct技术,实现了一个地区表的CRUD操作,并通过递归生成树状结构的AreaVo对象,便于前端展示。重点讲解了数据结构表设计、实体类映射以及MapStruct工具的运用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

表结构

DROP TABLE IF EXISTS `sys_area`;
CREATE TABLE `sys_area`  (
  `id` bigint(0) NOT NULL COMMENT '主键ID',
  `parent_id` bigint(0) NOT NULL COMMENT '上级ID',
  `level` int(0) NOT NULL COMMENT '当前节点等级',
  `name` varchar(55) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '名称(北京)',
  `ext_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '名称全称(北京市)',
  `spell` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '拼音全拼',
  `full_id_path` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'ID路径集合(省ID-市ID-区镇ID)',
  `full_value_path` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '名称路径集合',
  `zip_code` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '邮编',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '地区表(省市镇区联动)' ROW_FORMAT = Dynamic;

数据就不导入了,太多了

实体

public class SysAreaEntity implements Serializable {

	/**
	 * 主键ID
	 */
	@TableId
	private Long id;
	/**
	 * 上级ID
	 */
	private Long parentId;
	/**
	 * 当前节点等级
	 */
	private Integer level;
	/**
	 * 名称(北京)
	 */
	private String name;
	/**
	 * 名称全称(北京市)
	 */
	private String extName;
	/**
	 * 拼音全拼
	 */
	private String spell;
	/**
	 * ID路径集合(省ID-市ID-区镇ID)
	 */
	private String fullIdPath;
	/**
	 * 名称路径集合
	 */
	private String fullValuePath;
	/**
	 * 邮编
	 */
	private String zipCode;

// 作用是,当为空的时候,不返回
	@JsonInclude(value = JsonInclude.Include.NON_EMPTY)
	@TableField(exist = false)
	List<SysAreaEntity> children;
	// 省略 get以及set
}

注意:不要使用lombok

service方法


@Service
public class AreaTreeService {

    @Autowired
    private SysAreaMapper areaMapper;

    @Autowired
    MapStructUtil mapStructUtil;
    public List<TreeVo> areaTree() {
        List<SysAreaEntity> areaList = areaMapper.selectList(null);

        List<SysAreaEntity> collect = areaList
                .stream()
                .filter(area -> area.getParentId() == 0)
                .map((menu) -> {
                    menu.setChildren(getChildren(menu, areaList));
                    return menu;
                }).collect(Collectors.toList());
        List<TreeVo> treeVos = mapStructUtil.toTreeVo(collect);
        return treeVos;
    }

    private List<SysAreaEntity> getChildren(SysAreaEntity menu, List<SysAreaEntity> all) {
        List<SysAreaEntity> children = all.stream().filter(
                cate -> {
                    return cate.getParentId().equals(menu.getId());
                }
        ).map(cate -> {
            cate.setChildren(getChildren(cate, all));
            return cate;
        }).collect(Collectors.toList());
        return children;
    }


}

这里我单独弄了一个vo进行返回,用到了MapStruct,不会的话,可以看我以前的文章。
mapStruct使用

@Mapper(componentModel = "spring", uses = StructHelper.class)
public interface MapStructUtil {

    List<TreeVo> toTreeVo(List<SysAreaEntity> entityList);

    @Mappings({
            @Mapping(source = "id",target = "id"),
            @Mapping(source = "parentId",target = "parentId"),
            @Mapping(source = "level",target = "level"),
            @Mapping(source = "extName",target = "extName"),
    })
    TreeVo toTreeVo( SysAreaEntity entity);
}

出参

// todo 切记不要用lomdata
public class TreeVo {
    private Long id;
    private Long parentId;
    private Integer level;
    private String extName;

    @JsonInclude(value = JsonInclude.Include.NON_EMPTY)
    List<TreeVo> children;
}
[
  {
    "id": 110000,
    "parentId": 0,
    "level": 1,
    "extName": "北京市",
    "children": [
      {
        "id": 110100,
        "parentId": 110000,
        "level": 2,
        "extName": "市辖区",
        "children": [
          {
            "id": 110101,
            "parentId": 110100,
            "level": 3,
            "extName": "东城区"
          },
          {
            "id": 110102,
            "parentId": 110100,
            "level": 3,
            "extName": "西城区"
          },
          {
            "id": 110105,
            "parentId": 110100,
            "level": 3,
            "extName": "朝阳区"
          },
          {
            "id": 110106,
            "parentId": 110100,
            "level": 3,
            "extName": "丰台区"
          },
          {
            "id": 110107,
            "parentId": 110100,
            "level": 3,
            "extName": "石景山区"
          },
          {
            "id": 110108,
            "parentId": 110100,
            "level": 3,
            "extName": "海淀区"
          },
          {
            "id": 110109,
            "parentId": 110100,
            "level": 3,
            "extName": "门头沟区"
          },
          {
            "id": 110111,
            "parentId": 110100,
            "level": 3,
            "extName": "房山区"
          },
          {
            "id": 110112,
            "parentId": 110100,
            "level": 3,
            "extName": "通州区"
          },
          {
            "id": 110113,
            "parentId": 110100,
            "level": 3,
            "extName": "顺义区"
          },
          {
            "id": 110114,
            "parentId": 110100,
            "level": 3,
            "extName": "昌平区"
          },
          {
            "id": 110115,
            "parentId": 110100,
            "level": 3,
            "extName": "大兴区"
          },
          {
            "id": 110116,
            "parentId": 110100,
            "level": 3,
            "extName": "怀柔区"
          },
          {
            "id": 110117,
            "parentId": 110100,
            "level": 3,
            "extName": "平谷区"
          },
          {
            "id": 110118,
            "parentId": 110100,
            "level": 3,
            "extName": "密云区"
          },
          {
            "id": 110119,
            "parentId": 110100,
            "level": 3,
            "extName": "延庆区"
          }
        ]
      }
    ]
  },

小总结

1-这个数据就是死的。可以输出到一个json文件中让前端去读。要是产品菜单,可以放到redis中,以加快网页加载速度。
2-递归的理解。递归方法的作用,这一层到下一层的条件,结束递归的条件。不考虑好容易挂。
3-MapStruct这个工具还听好用。学习成本也不是很大。新手俩个小时左右。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值