Spring Boot中实现一个递归获取省市区行政区划代码

Spring Boot中实现一个递归获取省市区行政区划代码

写于20240924 10:23

在Spring Boot中实现一个递归获取省市区行政区划代码的功能,可以按照以下步骤进行。我们将使用Spring Data JPA来与数据库交互,并构建一个递归的方法来获取层级数据。
首先这里数据库使用
mysql
jdk17
springboot3.3.2


下面开始实际案例分析:

1、定义实体类 Geographic

首先,定义一个实体类 Geographic,它将映射到数据库中的行政区划表。假设表中有字段 idnameparentId 来表示每个区域的唯一标识、名称及其父区域的ID。

package com.dependencies.springdatajpa.entity;

import jakarta.persistence.*;
import lombok.Data;

import java.util.ArrayList;
import java.util.List;

/**
 * @author zhizhou   2024/9/24 09:56
 */
@Data
@Entity
@Table(name = "geographic")
public class Geographic {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String name;
    
    private String code;
    
    @Column(name = "parent_id")
    private Long parentId;
    
    @Transient
    private List<Geographic> children = new ArrayList<>();
}

2、创建 GeographicRepository

使用Spring Data JPA创建一个仓库接口,以便于查询数据库。

package com.dependencies.springdatajpa.repository;

import com.dependencies.springdatajpa.entity.Geographic;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.List;

/**
 * @author zhizhou   2024/9/24 09:55
 */
@Repository
public interface GeographicRepository extends JpaRepository<Geographic, Long> { 
    List<Geographic> findByParentId(Long parentId);
}

3、实现 GeographicService

在服务层中实现递归获取行政区划数据的方法 getGeographicListData

package com.dependencies.springdatajpa.service;

import com.dependencies.springdatajpa.entity.Geographic;
import com.dependencies.springdatajpa.repository.GeographicRepository;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.List;

/**
 * @author zhizhou   2024/9/24 09:55
 */
@Service
public class GeographicService {
    
    @Autowired
    private GeographicRepository geographicRepository;
    
    /**
     * V2 递归获取行政区划数据
     * @param parentId 父级ID,根节点传入null或0
     * @return 行政区划列表
     */
    public List<Geographic> getGeographicListData(Long parentId) {
        List<Geographic> list = geographicRepository.findByParentId(parentId);
        for (Geographic geographic : list) {
            // 递归获取子节点
            List<Geographic> children = getGeographicListData(geographic.getId());
            geographic.setChildren(children);
        }
        return list;
    }
    
  
    //V2 批量查询:一次性查询所有数据,并在内存中构建树结构
    public List<Geographic> getGeographicListDataAll(Long parentId) {
        List<Geographic> allGeographics = geographicRepository.findAll();
        return buildTree(allGeographics, parentId);
    }
    
    private List<Geographic> buildTree(List<Geographic> all, Long parentId) {
        List<Geographic> tree = new ArrayList<>();
        for (Geographic geo : all) {
            if (geo.getParentId().equals(parentId)) {
                geo.setChildren(buildTree(all, geo.getId()));
                tree.add(geo);
            }
        }
        return tree;
    }
    
}

4、创建 GeographicController 控制器

为了让前端能够调用该服务,我们可以创建一个控制器来暴露一个REST API端点。

获取行政区划列表这里提供了两种思路,依据实际场景进行实践,数据层级相对较小并发量较小时都可以采用,但当书记层级较深,频繁的查询数据库会造成没必要的资源消耗。

这里推荐第二种方案,批量查询:一次性查询所有数据,并在内存中构建树结构,省市区大概3180多条,数据量相对还好,内存大概不到1M,500KB左右。

package com.dependencies.springdatajpa.controller;

import com.dependencies.springdatajpa.entity.Geographic;
import com.dependencies.springdatajpa.service.GeographicService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * @author zhizhou   2024/9/24 09:54
 */
@RestController
@RequestMapping("/api/geographics")
public class GeographicController {
    @Autowired
    private GeographicService geographicService;
    
    /**
     * 获取行政区划列表(遍历查询数据库)
     * @param parentId 父级ID,可选参数,根节点传入null或不传
     * @return 行政区划列表
     */
    @GetMapping
    public List<Geographic> getGeographics(@RequestParam(value = "parentId", required = false) Long parentId) {
        // 如果parentId为空,设为0或null,根据实际情况
        if (parentId == null) {
            parentId = 0L; // 假设根节点的parentId为0
        }
        return geographicService.getGeographicListData(parentId);
    }
    
    /**
     * 获取行政区划列表(批量查询:一次性查询所有数据,并在内存中构建树结构,省市区大概3180多条,数据量相对还好,内存大概不到1M,500KB左右)
     * @param parentId 父级ID,可选参数,根节点传入null或不传
     * @return 行政区划列表
     */
    @GetMapping(value="/all")
    public List<Geographic> getGeographicsAll(@RequestParam(value = "parentId", required = false) Long parentId) {
        // 如果parentId为空,设为0或null,根据实际情况
        if (parentId == null) {
            parentId = 0L; // 假设根节点的parentId为0
        }
        return geographicService.getGeographicListDataAll(parentId);
    }  
}

5、数据库配置文件

确保在 application.properties 中正确配置了数据库连接。使用MySQL数据库:

spring.application.name=spring-data-jpa

# MySQL Database configuration
spring.datasource.url=jdbc:mysql://localhost:3306/spring-dependencies?useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

6、 示例数据

确保数据库中有相应的行政区划数据。例如:

idnamecodeparent_id
1北京市1100000
2朝阳区1101051
3海淀区1101081
4上海市3100000
5浦东新区3101154
6徐汇区3101044

7、debug测试

启动Spring Boot应用后,可以通过以下方式测试API:

  • 获取所有省级行政区(假设parentId=0为省级)

    GET http://localhost:8080/api/geographics?parentId=0
    
  • 获取特定省市的子级行政区

    GET http://localhost:8080/api/geographics?parentId=1
    
  • 获取特定省市的子级行政区

    GET http://localhost:8080/api/geographics/all?parentId=1
    

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值