基于ApachePOI实现高德POI分类快速导入PostgreSQL数据库实战

发布于:2025-07-15 ⋅ 阅读:(15) ⋅ 点赞:(0)

目录

前言

一、高德POI分类简介

1、数据表格

2、分类结构

二、从Excel导入到Postgresql

1、Excel解析流程

2、Mybatis批量导入

3、数据入库

三、总结


前言

        在大数据与地理信息深度交融的当下,地理信息系统(GIS)的触角已延伸至各个领域,为行业决策提供精准的空间数据支撑。而 POI(Point of Interest,兴趣点)分类数据,作为 GIS 数据的细分瑰宝,正发挥着独特且关键的作用。高德地图所涵盖的丰富 POI 分类数据,如美食、电影院、酒店、购物场所等,宛如一座有待深度挖掘的宝藏,对商业选址、城市规划、旅游服务等行业有着不可估量的价值。

        以商业领域为例,掌握准确的美食分类 POI 数据,能助力餐饮企业洞察竞争对手分布、分析区域市场潜力,为新店选址提供科学依据;而电影院分类数据则可辅助院线优化布局,甚至为周边配套商业设施的规划提供参考。但目前,要将这些高德 POI 分类数据高效整合到分析系统中并非易事。一方面,高德提供的 POI 分类数据获取往往存在一定限制和规则,开发者需要巧妙设计数据采集策略;另一方面,采集后的数据多存储于 Excel 表格中,格式多样且字段特性各异,要将其批量、快速且准确地导入到数据库,实现与信息系统无缝对接,是一道亟待攻克的技术难关。

        PostgreSQL 凭借其卓越的开源特性和对地理空间数据的强大支持能力,成为众多开发者存储和管理 POI 分类数据的首选数据库。而 ApachePOI 则是 Java 开发领域处理 Excel 文件的得力工具。本实战将聚焦于如何运用 ApachePOI,将高德 POI 分类数据(美食、电影院等类别)从 Excel 快速导入到 PostgreSQL 数据库的全过程。

        在此过程中,我们将深入剖析 Excel 中 POI 分类数据的存储结构特点,针对美食、电影院等不同分类数据字段特性,制定对应的映射规则与转换策略,还将着重探索如何优化导入流程,提升数据导入效率,减少系统资源消耗。通过本次实战,不仅能为开发者揭开高德 POI 分类数据导入的神秘面纱,也为各类基于 POI 分类数据的地理信息系统开发、商业智能分析以及城市规划应用等,铺设一条从数据获取到存储利用的高效路径,助力行业在空间数据赋能下实现精准决策与创新发展。

一、高德POI分类简介

        本节将首先重点介绍高德地图的POI分类信息,在之前的博客中我们设计了用于POI管理的物理表,希望可以用来存储对应的POI分类信息。然后使用数据库脚本的方法对POI分类信息进行录入管理。而对于高德地图而言,其POI的分类是非常详细的,因此这一节我们来详细的解读一下高德的POI分类,让大家对分类信息有进一步的了解,为下一步数据的批量解析入库打下牢固的基础。

1、数据表格

        大家可以从高德的地图开放平台中获取其最新的POI分类的Excel表格,这里我将从官网下载的类型截取一部分给大家参考,数据表格一共有32页太多,这里不进行赘述,需要原始Excel表格的,可以去网站上下载。

        在Excel表格中,一共提供了8个关键信息,分别是:

序号 字段名 说明
1 序号 数据的序号,如:1
2 NEW_TYPE POI分类编码,如:010000
3 大类 POI大类,如:汽车服务
4 中类 POI中类,如:加油站
5 小类 POI小类,如:中国石化
6 Big Category POI大类英文,如:Auto Service
7 Mid  Category POI中类英文,如:Filling Station
8 Sub Category POI小类英文,如:Sinopec

         从上面的数据表格和字段信息介绍可以知道,高德地图的POI分类按照类别分成大、中、小分成了三类,同时有对应的英文类别说明。同样的,基于高德地图的POI检索可以从返回接口中看到其对应的POI分类值为:

{
	"address": "茶子山路与银杉路交叉口东北60米",
	"business": {
		"opentime_today": "17:00-01:00",
		cost": "61.00",
		"keytag": "大排档",
		"rating": "4.5",
		"business_area": "湘江新区",
		"tel": "15873178255",
		"tag": "大排档",
		"rectag": "大排档",
		"opentime_week": "周一至周日 17:00-01:00"
	},
	"pcode": "430000",
	"adcode": "430104",
	"pname": "湖南省",
	"cityname": "长沙市",
	"type": "餐饮服务;中餐厅;中餐厅",
	"typecode": "050100",
	"adname": "岳麓区",
	"citycode": "0731",
	"navi": {
		"navi_poiid": "H49F046040_387534",
		"gridcode": "4212278620"
	},
	"name": "二五八大排档(茶子山路店)",
	"indoor": {
		"indoor_map": "0"
	},
	"location": "112.952067,28.241331",
	"id": "B0FFIK20N1"
}

        其中type和typecode分别对应poi分类的类别和poi编码,需要注意的是,调用高德地图返回的POI中,POI分类都是返回到了小类。 

2、分类结构

        在了解了高德地图的POI分类之后,下面我们基于之前设计的数据库物理表和分类信息构建树形的信息,为了方便在后面的查询中可以根据POI的大类、中类、小类来进行查询。就不能直接存储小类,而需要对其分类采取细致的分类管理。在进行树形层次构建时,我们根据编码来进行统一管理:

        这个结构是其编码分类的基础,也是后面的数据程序解析的基础。我们将使用编码来进行三级分类的解析及入库。 在Excel中,很大的大类和种类都是重复的,因此需要在入库时将类别进行去重分类,最终构建一棵完整的POI分类树。

二、从Excel导入到Postgresql

        本节将详细介绍在Java中使用ApachePOI实现从Excel中解析到存储至PostgreSQL中,主要包含两个方面,第一个是如何结合POI分类的规则进行分类解析。第二个方面是如何基于Mybatis实现程序的批量入库。完整的数据处理流程如下:

1、Excel解析流程

        在进行POI的分类进行构建尤其重要,为了防止各层级在构建时出现重复的情况,这里采用LinkedHashMap集合来进行重复判断,在存储集合对象时,将分类编码作为map的key,而具体分类对象作为value。在后续的对象去重判断时,key就是重复的标记。为了实现Excel数据的导入,需要定义一个JavaBean来读取数据,其关键代码如下:

package com.yelang.project.poisubject.poi.domain;
import java.io.Serializable;
import com.yelang.framework.aspectj.lang.annotation.Excel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
 * - 高德POI分类Excel视图对象
 * @author 夜郎king
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class AmapPoiCategoryExcelVO implements Serializable{
	private static final long serialVersionUID = 2795552725033725828L;
	@Excel(name = "NEW_TYPE")
	private String poiType;//高德的POI类
	@Excel(name = "大类")
    private String bigCategory;//中文大类
	@Excel(name = "中类")
    private String midCategory;//中文中类
	@Excel(name = "小类")
    private String subCategory;//中文小类
	@Excel(name = "Big Category")
    private String bigCategoryEn;//英文大类
	@Excel(name = "Mid  Category")
    private String midCategoryEn;//英文中类
	@Excel(name = "Sub Category")
    private String subCategoryEn;//英文小类
}

         接下来读取Excel的数据,按照分类对高德POI分类进行层级重建,核心代码如下:

File file = new File(AMAP_POI_FILE);
FileInputStream fis = new FileInputStream(file);
ExcelUtil<AmapPoiCategoryExcelVO> util = new ExcelUtil<AmapPoiCategoryExcelVO>(AmapPoiCategoryExcelVO.class);
List<AmapPoiCategoryExcelVO> dataList = util.importExcel(fis);
LinkedHashMap<String,PoiCategory> amapPoiTypeMap = new LinkedHashMap<String, PoiCategory>();
for(AmapPoiCategoryExcelVO poiCategory : dataList) {
	String type = poiCategory.getPoiType();
    String bigCategory = poiCategory.getBigCategory();
    String midCategory = poiCategory.getMidCategory();
    String subCategory = poiCategory.getSubCategory(); 
    String bigCategoryEn = poiCategory.getBigCategoryEn();
    String midCategoryEn = poiCategory.getBigCategoryEn();
    String subCategoryEn = poiCategory.getSubCategoryEn();
    String bigCategorySno = type.substring(0, 2);
    String midCategorySno = type.substring(0, 4);
    //不包含大类,添加到集合中
    if(!amapPoiTypeMap.containsKey(bigCategorySno)) {
         PoiCategory category = new PoiCategory(IdWorker.getId(),101L,"0,100,101",bigCategory,bigCategoryEn,bigCategorySno);
                	amapPoiTypeMap.put(bigCategorySno, category);
     }
     //不包含中类,添加到集合中
     if(!amapPoiTypeMap.containsKey(midCategorySno)) {
         String parentKey = midCategorySno.substring(0, 2);
         PoiCategory parentCategory = amapPoiTypeMap.get(parentKey);
         String ancestors = parentCategory.getAncestors() + "," + parentCategory.getPkId();
         PoiCategory category = new PoiCategory(IdWorker.getId(),parentCategory.getPkId(),ancestors,midCategory,midCategoryEn,midCategorySno);
         amapPoiTypeMap.put(midCategorySno, category);
      }
      //不包含小类,添加到集合中
      if(!amapPoiTypeMap.containsKey(type)) {
          String parentKey = midCategorySno.substring(0, 4);
          PoiCategory parentCategory = amapPoiTypeMap.get(parentKey);
          String ancestors = parentCategory.getAncestors() + "," + parentCategory.getPkId();
          PoiCategory category = new PoiCategory(IdWorker.getId(),parentCategory.getPkId(),ancestors,subCategory,subCategoryEn,type);
          amapPoiTypeMap.put(type, category);
       }
}

2、Mybatis批量导入

        基于Mybatis的批量导入,这里介绍基于Xml的批量操作,需要在创建的Mapper.xml文件中定义以下内容:

<insert id="batchInsertPoiCategory" parameterType="java.util.List">
 		insert into biz_poi_category ( pk_id,parent_id,category_name,ancestors,order_num,origin_code,category_english_name,platform,status,del_flag,create_time) values 
 		<foreach collection="list" item="item" separator=",">
	        ( #{item.pkId},#{item.parentId},#{item.categoryName},#{item.ancestors},
#{item.orderNum},#{item.originCode},#{item.categoryEnglishName},#{item.platform},#{item.status},#{item.delFlag},
	            now()
	        )
	    </foreach>
</insert>

        在Mapper及业务逻辑层的批量保存方法比较简单,这里提供业务层的一个简单调用示例:

/**
* - 批量插入POI目录信息
* @param list
*/
@Override
public void batchInsertPoiCategory(List<PoiCategory> list) {
   this.poiCategoryMapper.batchInsertPoiCategory(list);
}

3、数据入库

        在数据入库之前,需要统一设置数据来源,如标记高德,设置删除标记、数据业务状态、数据创建时间等,这些都是非常重要的,设置公共数据后就可以调用之前提供的批量入库的方法进行插入数据库操作,关键方法如下所示:

List<PoiCategory> categoryData = new ArrayList<PoiCategory>();
for (PoiCategory value : amapPoiTypeMap.values()) {
     value.setPlatform("gaode");
     value.setDelFlag(0);
     value.setStatus(0);
     value.setOrderNum(1);
     value.setCreateTime(DateUtils.getNowDate());
     categoryData.add(value);
}
//数据入库 
poiCateGoryService.batchInsertPoiCategory(categoryData);
System.out.println("finished...");

        完成以上的操作后就完成了高德POI分类数据的Postgresql数据库导入操作,导入完成后就可以在数据库中查看,如下图所示:

        支持,完全实现基于ApachePoi的高德POI分类数据导入处理操作。 

三、总结

        以上就是本文的主要内容,在本文中我们将深入剖析 Excel 中 POI 分类数据的存储结构特点,针对美食、电影院等不同分类数据字段特性,制定对应的映射规则与转换策略,还将着重探索如何优化导入流程,提升数据导入效率,减少系统资源消耗。通过本次实战,不仅能为开发者揭开高德 POI 分类数据导入的神秘面纱,也为各类基于 POI 分类数据的地理信息系统开发、商业智能分析以及城市规划应用等,铺设一条从数据获取到存储利用的高效路径,助力行业在空间数据赋能下实现精准决策与创新发展。行文仓促,难免有许多不足之处,如有不足,在此恳请各位专家博主在评论区不吝留言指出,不胜感激。


网站公告

今日签到

点亮在社区的每一天
去签到