在Java中使用ModelMapper简化Shapefile属性转JavaBean实战过程

2025-02-12 05:50

本文主要是介绍在Java中使用ModelMapper简化Shapefile属性转JavaBean实战过程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《在Java中使用ModelMapper简化Shapefile属性转JavaBean实战过程》本文介绍了在Java中使用ModelMapper库简化Shapefile属性转JavaBean的过程,对比...

前言

        在现代软件开发中,尤其是在多层架构中,经常需要将数据从一个域对象转换到另一个域对象,或者从数据库结果集转换到业务对象。手动编写这些转换代码不仅耗时,而且容易出错。我们需要一种自动化的方式来处理这些转换,减少了开发工作量和潜在的错误。JavaBean是一种遵循特定编写规范的Java类,通常具有get和set方法来访问私有属性,以及一个无参构造函数。JavaBean是我们平时的开发过程当中遇到最多的类,不管它是DO、DTO、VO或者POJO等等,这些类都是以JavaBean的形式存在的。

在Java中使用ModelMapper简化Shapefile属性转JavaBean实战过程

        在之前的系列博客中,尤其是涉及空间数据管理和查询的后台设计中。大家如果认真注意的话,我们分别在空间数据库中创建一张与属性字段对应的空间表。而在采用MVC的开发模式中,模型层通常会对应一个与空间表对应的空间表。与成熟的ORM映射不同的是,ORM框架自动的会将数据库中的字段快速得与JavaBean的属性进行对应,在执行查询语句的时候可以直接关联。但是在处理空间数据时,比如使用GDAL或者GeoTools来进行数据读取时,目前暂时没有找到成熟的框架或者组件支持空间属性表与JavaBean的快速映射需求。

        本文以Java语言为例,主要讲解如何使用Java语言进行空间数据的读取,空间属性信息的读取使用GeoTools,文章首先介绍最原始的做法,即在对象中自定义转换方法来实现转换,然后详细介绍一种基于ModelMapper的空间属性映射实现方法。ModelMapper在Java的其它领域应用很多,但是在GIS领域中使用的还不多。如果您是一名GISER,同时也面临着属性信息映射的问题,不妨来这里交流讨论。

一、原始的处理办法

        在介绍本文的处理办法之前,首先依然来看一下最原始的处理办法是什么。由此,可以对比不同的处理办法的不同点,也可以发现其有点。关于如何读取空间属性信息,不管是使用GDAL或者GeoTools,不管是Gdb数据或者Shapefile数据,之前的系列博客都进行了简单的说明。因此想了解具体的读取过程的,可以翻阅之前的博客。因此这里只将转换的过程进行说明。

1、使用Set方法来转换

        首先来介绍调用对象实例的Set方法来进行转换。这种情况使用与空间属性表的字段不是很多,我们在转换时可以先从空间属性表中分别读取出具体的字段,然后再调用对应的JavaBea的Set方法来进行字段的映射和转换。比如在进行省份的空间属性信息转换的代码如下所示:

List<Province> list = new ArrayList<Province>();
for (int i = 0; i < featureCount; i++) {
	Feature feature = layer.GetFeature(i);
	String code = feature.GetFieldAsString("province_c");
	String name = feature.GetFieldAsString("province_n");
	String type = feature.GetFieldAsString("type");
	Geometry geom = feature.GetGeometryRef();
	String wkt = geom.ExportToWkt();
	Province p = new Province();
	p.setCode(code);
	p.setName(name);
	p.setType(type);
	p.setGeom(wkt);
}

        上面是一个使用GDAL解析空间数据时的属性映射的实例代码。 这种方式相信大家很熟悉,通过创建Province对象后,再分别从feature中读取省份信息,最后设置到实例对象中,最后再保存到数据库中。

2、使用构造方法转换

        除了使用set方法来进行设置,我们也可以使用构造方法来进行属性赋值。与set方法相比,构造方法可以统一设置,不需逐行进行设置。这样代码显得比较优雅,可读性也高。构造方法是将属性赋值的过程抽象都对象的构造方法中,这样实现代码的整体复用。这里以城市对象构造方法为例:

public City(String provinceCode, String provinceName, String cityCode, String cityName, String type, String geom) {
	super();
	this.provinceCode = provinceCode;
	this.provinceName = provinceName;
	this.cityCode = cityCode;
	this.cityName = cityName;
	this.type = type;
	this.geom = geom;
}

    &nbgMdqBDGObsp;   然后在解析的过程中就可以直接调用构造方法的模式简化设置的过程,代码如下:

List<City> list = new ArrayList<City>();
for (int i = 0; i < featureCount; i++) {
	Feature feature = layer.GetFeature(i);
	String code = feature.GetFieldAsString("province_c");
	String name = feature.GetFieldAsString("province_n");
	String cityCode = feature.GetFieldAsString("city_code");
	String cityName = feature.GetFieldAsString("city_name");
	String type = feature.GetFieldAsString("type");
	Geometry geom = feature.GetGeometryRef();
    String wktjs = geom.ExportToWkt();
	list.add(new City(code,name,cityCode,cityName,type,wkt));
}
cityService.saveBATch(list,100);

        可以从代码中看到,通过构造方法的方式来进行赋值,能极大的减少set方法的调用,能减少许多的代码调用。可以看到,不管使用哪种方式,我们都需要有一个从feature中根据属性名解析字段,不得不说,这种方式于我们最开始学JDBC的模式非常相似,那么有什么办法实现动态映射,不需要单独读取呢?下面我们就来分享一种方法来进行转换。

二、基于ModelMapper的动态转换

        既然有了如上的需求场景,那么有什么方法可以实现快速的属性映射吗?在Java当中,很多人首选肯定是采用反射,对吧。确实如此,使用反射可以解决我们的问题,实现上述的需求。对于反射,相信很多的朋友可以自行进行编码。本着不重复造轮子的思路,我们可以从现有的一些成熟工具中来选择符合我们期望的组件。这里推荐一款转换组件,ModelMapper。

1、ModelMapper简介

        ModelMapper是一个Java对象映射库,它能够将一个对象的数据映射到另一个对象中,从而避免手动编写数据转换代码。ModelMapper通过使用简单的配置和API,能够自动地将源对象的属性复制到目标对象的属性中,这在处理不同数据层之间的数据转换时非常有用。ModelMapper简化了开发流程,因为它减少了手动编写数据转换代码的需要。这不仅提高了开发效率,还使得代码更加简洁和易于维护。通过使用ModelMapper,开发者可以将更多的精力投入到业务逻辑的实现上,而不是数据转换的细节上。ModelMapper提供了高度的灵活性和可配置性。开发者可以根据需要自定义映射规则,例如跳过某些属性的映射,或者在映射过程中进行条件判断和自定义转换。这种灵活性使得ModelMapper能够适应各种复杂的数据转换场景。

        首先,我们来看一下ModelMapper的官网介绍,modelmapper官网。大家可以先到js官网看一下它的相关介绍可帮助文档。

在Java中使用ModelMapper简化Shapefile属性转JavaBean实战过程

2、集成到项目中

        对ModelMapper有了基本的了解之后,我们来看一下如何将ModelMapper集成到Java项目当中。首先我们需要使用Maven来进行资源的引入,在Pom.XML中引入依赖,关键代码如下所示:

<!--  增加模型映射 add by 夜郎king in 2024.11.11 begin -->
<!-- https://mvnrepository.com/artifact/org.modelmapper/modelmapper -->
<dependency>
	<groupId>org.modelmapper</groupId>
	<artifactId>modelmapper</artifactId>
	<version>3.1.1</version>
</dependency>
<!--  modelmapper add by 夜郎king in 2024.11.11 end -->

        然后在Java中进行相应的集成,虽然ModelMapper本身主要作用是用于JavaBean之间的转换,但是也可以在Map和JavaBean之间进行属性映射。

@Test
public void convertMap2BeanWithUnderscoreNamingConvention() {
	HashMap<String, Object> map = new HashMap<String, Object>();
	map.put("scalerank", 6);
	map.put("LS_NAME", "test241111");
	map.put("MAX_POP10", "23562");
	ModelMapper modelMapper = new ModelMapper();
	Ne10mPopulatedPlaces pp = modelMapper.map(map, Ne10mPopulatedPlaces.class);
	System.out.println(pp);
	System.out.println(pp.getLsName());
	System.out.println(pp.getMaxPop10());
	assertEquals("test241111", pp.getLsName());
	assertEquals(23China编程562L, pp.getMaxPop10());
}

        代码很简单,首先定义一个HashMap,map的key是属性的名字,value是实际的值。然后我们创建ModelMapper,使用默认的转换策略和匹配模式,在这种策略下实现Map向Ne10mPopulatedPlaces对象的转换。Ne10mPopulatedPlaces对象就是之前提到过的人口城市空间属性数据。

在Java中使用ModelMapper简化Shapefile属性转JavaBean实战过程

        这个类的属性比较对,大概有137个属性。针对这么多的属性映射,不管是采用set方法还是构造方法,实现代码都会非常冗长。运行上面的测试方法后,可以看到如下结果:

在Java中使用ModelMapper简化Shapefile属性转JavaBean实战过程

3、Shapefile属性读取 

        有了以上的基础,结合之前的GeoTools的属性读取方法,我们来解析属性表格。解析的思路很简单,循环属性表格,将属性表列和值组成一个HashMap,表头为key,值为value的hashMap,然后将这个HashMap转换成对应的JavaBean对象。

@Test
public void convertDbf2BeanByDefault() throws Exception {
	File dbfFile = new File(SHP_FILE);
	ShpFiles shpFile = new ShpFiles(dbfFile);
	DbaseFileReader dbfReader = new DbaseFileReader(shpFile, true, Charset.defaultCharset());
	// 读取 DBF 文件的头信息
	DbaseFileHeader header = dbfReader.getHeader();
	List<Ne10mPopulatedPlaces> dataList = new ArrayList<Ne10mPopulatedPlaces>(header.getNumRecords());
	List<HashMap<String, Object>> mapList = new ArrayList<HashMap<String,Object>>();
	ModelMapper modelMapper = new ModelMapper();
	while (dbfReader.hasNext()) {
		Row row = dbfReader.readRow();
		HashMap<String, Object> map = new HashMap<String, Object>();
		for (int i = 0; i < header.getNumFields(); i++) {
			map.put(header.getFieldName(i), row.read(i));
		}
		mapList.add(map);
	}
	int index = 0;
	for(HashMap<String, Object> map : mapList) {
		if(index > 10) {
			break;
		}
		Ne10mPopulatedPlaces places = modelMapper.map(map, Ne10mPopulatedPlaces.class);
		System.out.println(places);
		dataList.add(places);
		index ++;
	}
	System.out.println(datjavascriptaList.size());
	System.out.println("属性字段数:" + header.getNumFields());
	System.out.println("数据记录数:" + header.getNumRecords());
	dbfReader.close();
}

        也是默认的映射策略和模式,通过上述的代码可以看到以下输出:

在Java中使用ModelMapper简化Shapefile属性转JavaBean实战过程

        可以看到, 通过以上的代码已经成功的实现把HashMap转换成JavaBean,同时可以看到JavaBean的属性值都成功的进行了赋值。到此,大功告成。

三、总结

        以上就是本文的主要内容,本文以Java语言为例,主要讲解如何使用Java语言进行空间数据的读取,空间属性信息的读取使用GeoTools,文章首先介绍最原始的做法,即在对象中自定义转换方法来实现转换,然后详细介绍一种基于ModelMapper的空间属性映射实现方法。ModelMapper在Java的其它领域应用很多,但是在GIS领域中使用的还不多。本文基于ModelMapper解决了在Shapefile文件读取过程中,如何实现动态的将属性表格映射到指定对象的方法进行了详细介绍。如果您是一名GISER,同时也面临着属性信息映射的问题,不妨来这里交流讨论。行文仓促,难免有许多不足之处,如有不足,还请各位专家朋友在评论区留言批评指正,不甚感激。

到此这篇关于在Java中使用ModelMapper简化Shapefile属性转JavaBean实战的文章就介绍到这了,更多相关Java转JavaBean内容请搜索编程China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持China编程(www.chinasem.cn)!

这篇关于在Java中使用ModelMapper简化Shapefile属性转JavaBean实战过程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1153405

相关文章

Java文件与Base64之间的转化方式

《Java文件与Base64之间的转化方式》这篇文章介绍了如何使用Java将文件(如图片、视频)转换为Base64编码,以及如何将Base64编码转换回文件,通过提供具体的工具类实现,作者希望帮助读者... 目录Java文件与Base64之间的转化1、文件转Base64工具类2、Base64转文件工具类3、

java获取图片的大小、宽度、高度方式

《java获取图片的大小、宽度、高度方式》文章介绍了如何将File对象转换为MultipartFile对象的过程,并分享了个人经验,希望能为读者提供参考... 目China编程录Java获取图片的大小、宽度、高度File对象(该对象里面是图片)MultipartFile对象(该对象里面是图片)总结java获取图片

CSS3中使用flex和grid实现等高元素布局的示例代码

《CSS3中使用flex和grid实现等高元素布局的示例代码》:本文主要介绍了使用CSS3中的Flexbox和Grid布局实现等高元素布局的方法,通过简单的两列实现、每行放置3列以及全部代码的展示,展示了这两种布局方式的实现细节和效果,详细内容请阅读本文,希望能对你有所帮助... 过往的实现方法是使用浮动加

Java通过反射获取方法参数名的方式小结

《Java通过反射获取方法参数名的方式小结》这篇文章主要为大家详细介绍了Java如何通过反射获取方法参数名的方式,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1、前言2、解决方式方式2.1: 添加编译参数配置 -parameters方式2.2: 使用Spring的内部工具类 -

Java如何获取视频文件的视频时长

《Java如何获取视频文件的视频时长》文章介绍了如何使用Java获取视频文件的视频时长,包括导入maven依赖和代码案例,同时,也讨论了在运行过程中遇到的SLF4J加载问题,并给出了解决方案... 目录Java获取视频文件的视频时长1、导入maven依赖2、代码案例3、SLF4J: Failed to lo

如何使用Spring boot的@Transactional进行事务管理

《如何使用Springboot的@Transactional进行事务管理》这篇文章介绍了SpringBoot中使用@Transactional注解进行声明式事务管理的详细信息,包括基本用法、核心配置... 目录一、前置条件二、基本用法1. 在方法上添加注解2. 在类上添加注解三、核心配置参数1. 传播行为(

c++中std::placeholders的使用方法

《c++中std::placeholders的使用方法》std::placeholders是C++标准库中的一个工具,用于在函数对象绑定时创建占位符,本文就来详细的介绍一下,具有一定的参考价值,感兴... 目录1. 基本概念2. 使用场景3. 示例示例 1:部分参数绑定示例 2:参数重排序4. 注意事项5.

使用C++将处理后的信号保存为PNG和TIFF格式

《使用C++将处理后的信号保存为PNG和TIFF格式》在信号处理领域,我们常常需要将处理结果以图像的形式保存下来,方便后续分析和展示,C++提供了多种库来处理图像数据,本文将介绍如何使用stb_ima... 目录1. PNG格式保存使用stb_imagephp_write库1.1 安装和包含库1.2 代码解

JAVA调用Deepseek的api完成基本对话简单代码示例

《JAVA调用Deepseek的api完成基本对话简单代码示例》:本文主要介绍JAVA调用Deepseek的api完成基本对话的相关资料,文中详细讲解了如何获取DeepSeekAPI密钥、添加H... 获取API密钥首先,从DeepSeek平台获取API密钥,用于身份验证。添加HTTP客户端依赖使用Jav

Java实现状态模式的示例代码

《Java实现状态模式的示例代码》状态模式是一种行为型设计模式,允许对象根据其内部状态改变行为,本文主要介绍了Java实现状态模式的示例代码,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来... 目录一、简介1、定义2、状态模式的结构二、Java实现案例1、电灯开关状态案例2、番茄工作法状态案例