如何将json行政区划导入数据库,中国行政区域数据(省市区县镇乡村五级联动)

目前用的是bladeX框架,

sql 复制代码
CREATE TABLE `blade_region_copy1` (
  `code` varchar(12) NOT NULL COMMENT '区划编号',
  `parent_code` varchar(12) DEFAULT NULL COMMENT '父区划编号',
  `ancestors` varchar(255) DEFAULT NULL COMMENT '祖区划编号',
  `name` varchar(128) DEFAULT NULL COMMENT '区划名称',
  `province_code` varchar(12) DEFAULT NULL COMMENT '省级区划编号',
  `province_name` varchar(128) DEFAULT NULL COMMENT '省级名称',
  `city_code` varchar(12) DEFAULT NULL COMMENT '市级区划编号',
  `city_name` varchar(128) DEFAULT NULL COMMENT '市级名称',
  `district_code` varchar(12) DEFAULT NULL COMMENT '区级区划编号',
  `district_name` varchar(128) DEFAULT NULL COMMENT '区级名称',
  `town_code` varchar(12) DEFAULT NULL COMMENT '镇级区划编号',
  `town_name` varchar(128) DEFAULT NULL COMMENT '镇级名称',
  `village_code` varchar(12) DEFAULT NULL COMMENT '村级区划编号',
  `village_name` varchar(128) DEFAULT NULL COMMENT '村级名称',
  `region_level` int(11) DEFAULT NULL COMMENT '层级',
  `sort` int(11) DEFAULT NULL COMMENT '排序',
  `remark` varchar(255) DEFAULT NULL COMMENT '备注',
  PRIMARY KEY (`code`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='行政区划表';

但是对于街道-社区 没有

目前从github找到了 行政区划json数据

中国行政区域数据(省市区县镇乡村五级联动)

https://github.com/657258535/China-Area-Region-Administrative-Divisions

最终效果如图:

数据库最终情况:

代码如下:

java 复制代码
/**
 * 行政区划
 *
 * @author rsz
 * @since 2025-06-13
 */
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/xingzheng")
public class xingzhengController {

	@Resource
	private ObjectMapper objectMapper;


	@Resource
	private IRegionService regionService;

	/**
	 * 上传TXT文件并解析为行政区划对象
	 * @param file 上传的TXT文件(内容为JSON)
	 * @return 解析后的行政区划对象
	 */
	@PostMapping("/api/division/parse")
	public R parseDivisionFile(@RequestParam("file") MultipartFile file) {
		// 1. 校验文件
		if (file.isEmpty()) {
			return R.fail("上传的文件不能为空");
		}


		try {
			// 2. 读取TXT文件内容(转成UTF-8编码的字符串)
			String jsonContent = IOUtils.toString(file.getInputStream(), StandardCharsets.UTF_8);
			log.info("读取到文件内容,长度:{} 字符", jsonContent.length());

			// 3. 用ObjectMapper解析JSON字符串为Division对象
			Division division = objectMapper.readValue(jsonContent, Division.class);

			// 4. 递归转换树形Division为平铺的Region列表
			List<Region> regionList = new ArrayList<>();
			// 初始化递归参数:当前节点、父节点code、层级、区编码/名称(初始为空)
			// 接口中调用递归方法的地方也要同步修改(新增townCode/townName初始值)
			// 初始化递归参数:祖编码初始为"",由1级节点自行拼接为"00"
			convertDivisionToRegion(division, "00", 1,
				null, null,  // 省级编码/名称
				null, null,  // 市级编码/名称
				null, null,  // 区级编码/名称
				null, null,  // 镇级编码/名称
				"",          // 祖编码初始值
				regionList);


			// 6. 保存所有Region到数据库
			regionService.saveBatch(regionList);

			// 5. 返回平铺的Region列表
			return R.success("成功");

		} catch (IOException e) {
			log.error("文件读取或JSON解析失败", e);
			return R.fail("解析失败:" + e.getMessage());
		}
	}
	/**
	 * 优化版递归方法:传递省/市/区/镇编码/名称+祖编码,实现全层级关联
	 */
	private void convertDivisionToRegion(Division division, String parentCode, Integer level,
										 String provinceCode, String provinceName,
										 String cityCode, String cityName,
										 String districtCode, String districtName,
										 String townCode, String townName,
										 String ancestors, // 新增:祖区划编号拼接字符串
										 List<Region> regionList) {
		// 1. 拼接当前节点的祖区划编号
		String currentAncestors;
		if (level == 1) { // 省级:祖编码固定为00
			currentAncestors = "00";
		} else { // 非省级:在父节点祖编码基础上追加父节点code
			currentAncestors = ancestors + "," + parentCode;
		}

		// 2. 创建当前节点的Region对象
		Region region = new Region();
		region.setCode(division.getCode());
		region.setParentCode(parentCode);
		region.setName(division.getName());
		region.setRegionLevel(level);
		region.setAncestors(currentAncestors); // 填充祖区划编号

		// 按层级填充字段
		if (level == 1) { // 省级
			// 填充省级字段
			region.setProvinceCode(division.getCode());
			region.setProvinceName(division.getName());
			provinceCode = division.getCode(); // 更新省级编码,供子节点使用
			provinceName = division.getName(); // 更新省级名称,供子节点使用
			// 市/区/镇/村字段为空
			region.setCityCode(null);
			region.setCityName(null);
			region.setDistrictCode(null);
			region.setDistrictName(null);
			region.setTownCode(null);
			region.setTownName(null);
			region.setVillageCode(null);
			region.setVillageName(null);
		} else if (level == 2) { // 市级
			// 继承省级字段
			region.setProvinceCode(provinceCode);
			region.setProvinceName(provinceName);
			// 填充市级字段
			region.setCityCode(division.getCode());
			region.setCityName(division.getName());
			cityCode = division.getCode(); // 更新市级编码,供子节点使用
			cityName = division.getName(); // 更新市级名称,供子节点使用
			// 区/镇/村字段为空
			region.setDistrictCode(null);
			region.setDistrictName(null);
			region.setTownCode(null);
			region.setTownName(null);
			region.setVillageCode(null);
			region.setVillageName(null);
		} else if (level == 3) { // 区级
			// 继承省/市级字段
			region.setProvinceCode(provinceCode);
			region.setProvinceName(provinceName);
			region.setCityCode(cityCode);
			region.setCityName(cityName);
			// 填充区级字段
			region.setDistrictCode(division.getCode());
			region.setDistrictName(division.getName());
			districtCode = division.getCode(); // 更新区级编码,供子节点使用
			districtName = division.getName(); // 更新区级名称,供子节点使用
			// 镇/村字段为空
			region.setTownCode(null);
			region.setTownName(null);
			region.setVillageCode(null);
			region.setVillageName(null);
		} else if (level == 4) { // 街道/镇级
			// 继承省/市/区级字段
			region.setProvinceCode(provinceCode);
			region.setProvinceName(provinceName);
			region.setCityCode(cityCode);
			region.setCityName(cityName);
			region.setDistrictCode(districtCode);
			region.setDistrictName(districtName);
			// 填充镇级字段
			region.setTownCode(division.getCode());
			region.setTownName(division.getName());
			townCode = division.getCode(); // 更新镇级编码,供子节点使用
			townName = division.getName(); // 更新镇级名称,供子节点使用
			// 村字段为空
			region.setVillageCode(null);
			region.setVillageName(null);
		} else if (level == 5) { // 社区/村级
			// 继承省/市/区/镇级字段
			region.setProvinceCode(provinceCode);
			region.setProvinceName(provinceName);
			region.setCityCode(cityCode);
			region.setCityName(cityName);
			region.setDistrictCode(districtCode);
			region.setDistrictName(districtName);
			region.setTownCode(townCode);
			region.setTownName(townName);
			// 填充村级字段
			region.setVillageCode(division.getCode());
			region.setVillageName(division.getName());
		}

		// 固定填充的字段
		region.setSort(1);
		region.setRemark(null);

		regionList.add(region);

		// 递归处理子节点(传递所有层级编码/名称)
		if (division.getChildren() != null && !division.getChildren().isEmpty()) {
			for (Division child : division.getChildren()) {
				convertDivisionToRegion(child, division.getCode(), level + 1,
					provinceCode, provinceName,
					cityCode, cityName,
					districtCode, districtName,
					townCode, townName,
					currentAncestors, // 传递当前节点的祖编码给子节点
					regionList);
			}
		}
	}


}
相关推荐
定仙游4531 小时前
Java StringBuilder 超详细讲解
java
haiyu柠檬2 小时前
IDEA和VSCode中好用的插件推荐
java·vscode·intellij-idea
怜淇2 小时前
docker拉取openjdk8:jre失败
java·docker·容器
降临-max2 小时前
JavaWeb企业级开发---Mybatis
java·开发语言·笔记·学习·mybatis
闲人不梦卿2 小时前
数据库安全和事务以及sql
数据库·sql
@22062 小时前
银河麒麟系统离线环境下用docke方式部署(Postgres、Nginx、Redis、JDK)
运维·数据库·redis·nginx
好好研究2 小时前
SpringBoot注解的作用
java·spring boot·spring
阿坤带你走近大数据2 小时前
oracle的varchar2(200)和mysql的varchar(200) 最大支持的字节数和字符数都一样吗
数据库·mysql·oracle
马克学长2 小时前
SSM新能源汽车销售管理系统gooct(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面
数据库·汽车·ssm框架·新能源汽车销售管理·车辆库存