文档章节

利用st_geometry进行图形叠加分析--结合mybatis

翻
 
发布于 2016/11/21 15:37
字数 1994
阅读 164
收藏 0
点赞 0
评论 0

在上一遍利用st_geometry进行图形叠加分析文章的基础上,结合mybatis操作st_geometry,主要简单实现一下三个功能:利用st_geometry两个表之间图形表的叠加分析、WKT与图形表的叠加分析、将WKT存储至数据图形表。

两个表之间图形表的叠加分析

构造sql

两个表之间图形表的叠加分析,先来创建一个专门构造sql的类,然后利用mybatis创建构造叠加分析的sql语句的方法

package com.zifan.st_geometry.mapper;

import java.lang.reflect.Field;

import org.apache.ibatis.jdbc.SQL;


public class STGeomertySqlBuilder {
	
	/**
	 * 
	 * @param srcTableName 源表表名字
	 * @param targetTableName 目标表的表名
	 * @param fields 返回表字段数据,如果两个表明字段都一样,要求添加前缀T或者S,例如T.OBJECTID
	 * @param where 原表数据条件,例如 objectId=100
	 * @return
	 */
	public String buildQueryIntersectByWhere(final String srcTableName, final String targetTableName,
			final String[] fields, final String where) {
		return new SQL() {
			{
				SELECT("SDE.ST_AREA(SDE.ST_TRANSFORM(S.SHAPE, #{srId})) SAREA");
				SELECT("SDE.ST_ASTEXT(SDE.ST_INTERSECTION(SDE.ST_TRANSFORM(T.SHAPE, #{srId}),SDE.ST_TRANSFORM(S.SHAPE, #{srId}))) OVERLAPCOORDS");
				SELECT("SDE.ST_AREA(SDE.ST_INTERSECTION(SDE.ST_TRANSFORM(T.SHAPE, #{srId}),SDE.ST_TRANSFORM(S.SHAPE, #{srId}))) OVERLAPAREA");
				if (fields != null) {
					for (String field : fields) {
						SELECT(field);
					}
				}
				FROM(srcTableName + " S").FROM(targetTableName + " T");//添加表别名
				WHERE("SDE.ST_INTERSECTS(T.SHAPE, S.SHAPE) = 1").AND().WHERE(where);
			}
		}.toString();
	}
}

上面buildQueryIntersectByWhere方法返回的是根据一个源表某条或者多条的图形数据与需要叠加分析的表的sql语句。返回的sql语句出了会返回指定的字段数据外,默认会返回源图形面积、叠加面积以及叠加图形的坐标串WKT。

mapper接口类

接下来进行实际叠加分析操作写mybatis的Mapper接口

package com.zifan.st_geometry.mapper;

import java.util.HashMap;
import java.util.List;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.SelectProvider;
import org.apache.ibatis.type.ClobTypeHandler;


@Mapper
public interface STGeometryMapper {

	@Results({@Result(property = "OVERLAPCOORDS", column = "OVERLAPCOORDS", javaType = String.class, typeHandler = ClobTypeHandler.class) })
	@SelectProvider(type = STGeomertySqlBuilder.class, method = "buildQueryIntersectByWhere")
	List<HashMap<String, Object>> queryIntersectByWhere(String srcTableName, String targetTableName, String[] fields,
			String where, @Param("srId") int srId);

}

这个方法返回的是List的HashMap,通过mybatis的注解SelectProvider定义此方法的查询语句。对于返回数据的处理,利用注解Results将返回的数据中包含叠加的WKT坐标串就涉及到CLOB大字段通过ClobTypeHandler类将转换成String类型。mybatis提供一个TypeHandler接口类,实现该接口处理要插入到数据库或者数据库返回的字段,ClobTypeHandler是mybatis自带的一个clob字段处理类。

测试

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class STGeometryTest {
	@Autowired
	private STGeometryMapper stGeometryMapper;	
	
	@Test
	public void test() {
		List<HashMap<String, Object>> map = stGeometryMapper.queryIntersectByWhere("TABLE1", "TABLE2",
				new String[] { "T.DL", "S.MC"}, "S.OBJECTID = 18133", 2);
		// System.out.println(net.minidev.json.JSONArray.toJSONString(map));
		Assert.assertEquals(4, map.size());

	}	
}

测试结果返回4条叠加数据,可以打印出来返回list的JSON数据看看,这里我省略的坐标的显示。

[
    {
        "SAREA": 19562.0006962064,
        "OVERLAPAREA": 2776.6041580972,
        "OVERLAPCOORDS": "POLYGON  (( ...))",
        "DL": "4419",
        "MC": "项目1"
    },
    {
        "SAREA": 19562.0006962064,
        "OVERLAPAREA": 14444.0513595036,
        "OVERLAPCOORDS": "MULTIPOLYGON  ((( ...)))",
        "DL": "4419",
        "MC": "项目2"
    },
    {
        "SAREA": 19562.0006962064,
        "OVERLAPAREA": 0.00205911626740205,
        "OVERLAPCOORDS": "POLYGON  (( ...))",
        "DL": "4419",
        "MC": "项目3"
    },
    {
        "SAREA": 19562.0006962064,
        "OVERLAPAREA": 2341.34313614271,
        "OVERLAPCOORDS": "POLYGON  (( ...))",
        "DL": "4419",
        "MC": "项目4"
    }
]

WKT与图形表的叠加分析

构造sql

同样通过mybatis来构造叠加分析的sql语句

    /**
	 * 
	 * @param targetTableName 叠加图层的表名
	 * @param fields 返回表字段数据
	 * @return
	 */
	public String buildQueryIntersectByWKT(final String targetTableName, final String[] fields) {
		return new SQL() {
			{
				SELECT("SDE.ST_AREA(SDE.ST_GEOMETRY(#{wkt,typeHandler=com.zifan.st_geometry.handler.STGeometryHandler}, #{srId})) SAREA");
				SELECT("SDE.ST_ASTEXT(SDE.ST_INTERSECTION(SDE.ST_TRANSFORM(SHAPE, #{srId}),SDE.ST_GEOMETRY(#{wkt,typeHandler=com.zifan.st_geometry.handler.STGeometryHandler}, #{srId}))) OVERLAPCOORDS");
				SELECT("SDE.ST_AREA(SDE.ST_INTERSECTION(SDE.ST_TRANSFORM(SHAPE, #{srId}),SDE.ST_GEOMETRY(#{wkt,typeHandler=com.zifan.st_geometry.handler.STGeometryHandler}, #{srId}))) OVERLAPAREA");
				if (fields != null) {
					for (String field : fields) {
						SELECT(field);
					}
				}
				FROM(targetTableName);
				WHERE("SDE.ST_INTERSECTS(SHAPE, SDE.ST_GEOMETRY(#{wkt,typeHandler=com.zifan.st_geometry.handler.STGeometryHandler}, #{srId})) = 1");
			}
		}.toString();
	}

自定义TypeHandler处理CLOB类型的WKT

上面方法中涉及到一个自定义的TypeHandler类,专门用来处理WKT字符转换成Clob,然后进行数据库操作。代码如下:

package com.zifan.st_geometry.mapper.handler;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;

import oracle.sql.CLOB;

public class STGeometryHandler extends BaseTypeHandler<String> {

	@Override
	public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType)
			throws SQLException {
		// TODO Auto-generated method stub
		CLOB clob = CLOB.createTemporary(ps.getConnection(), true, CLOB.DURATION_SESSION);
		clob.setString(1, parameter);//ojdbc14以上支持
		ps.setClob(i, clob);
	}

	@Override
	public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
		// TODO Auto-generated method stub
		return null;
	}

}

mybatis的Mapper接口方法实现

@Results({@Result(property = "OVERLAPCOORDS", column = "OVERLAPCOORDS", javaType = String.class, typeHandler = ClobTypeHandler.class) })
@SelectProvider(type = STGeomertySqlBuilder.class, method = "buildQueryIntersectByWKT")
List<HashMap<String, Object>> queryIntersectByWKT(String targetTableName, String[] fields, @Param("wkt") String wkt,
			@Param("srId") int srId);

返回结果与第一个功能的结果一样

测试

    @Test
	public void testIntersectByWKT() {
		String shortWkt = "POLYGON ((3 3, 4 6, 5 3, 3 3))";
		List<HashMap<String, Object>> map = intersect.queryIntersectByWKT("TB2013",
				new String[] { "DL", "MC"}, shortWkt, 2);
		// System.out.println(net.minidev.json.JSONArray.toJSONString(map));
		Assert.assertEquals(80, map .size());
	}

使用这种方法进行叠加分析要注意的是如果WKT坐标串越长这种方法执行的时间就越长,主要是由于这里的sql构造涉及了四个一模一样CLOB内容的输入。所以在更多情况下还是建议将这种方法变换成第一种的分析方法为好,具体就是先将WKT存储到临时的图形表中,然后才用表与表之间的分析方法进行叠加产生结果。

将WKT存储至数据图形表

创建图形数据基础类

这里我们先设计一个基础类,所有图形数据表都继承它,类属性有图形表名字、空间参考ID、objectId、wkt、表所在的数据库用户。代码:

package com.zifan.st_geometry.model;

public abstract class STGeometry {
	
	//主要用于生成OBJECTID
	private String tableName;
	//主要用于生成OBJECTID
	private String owner;
	private long objectId;
	private int srId;
	private String wkt;

	public int getSrId() {
		return srId;
	}

	public void setSrId(int srId) {
		this.srId = srId;
	}

	public String getWkt() {
		return wkt;
	}

	public void setWkt(String wkt) {
		this.wkt = wkt;
	}

	public long getObjectId() {
		return objectId;
	}

	public void setObjectId(long objectId) {
		this.objectId = objectId;
	}

	public String getTableName() {
		if (tableName == null) {
			// 默认获取类名称
			tableName = this.getClass().getSimpleName();
		}
		return tableName;
	}

	public void setTableName(String tableName) {
		this.tableName = tableName;
	}

	public String getOwner() {
		return owner;
	}

	public void setOwner(String owner) {
		this.owner = owner;
	}

}

这里有两个字段需要说明一下,tableName、Owner,他们主要是用于产生图形数据中的主键OBJECTID的,查找下一个OBJECTID的sql语句:

SELECT SDE.VERSION_USER_DDL.NEXT_ROW_ID(UPPER('gis')
                                        (SELECT REGISTRATION_ID
                                           FROM SDE.TABLE_REGISTRY
                                          WHERE TABLE_NAME = UPPER('tb')
                                            AND OWNER = UPPER('gis'))) AS OBJECTID

构造sql

public String buildInsertSql(final STGeometry geometry)
			throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
		return new SQL() {
			{
				INSERT_INTO(geometry.getTableName());
				Field[] fieldList = geometry.getClass().getDeclaredFields();
				for (Field field : fieldList) {
					String methodName = "get".concat(field.getName().substring(0, 1).toUpperCase())
							.concat(field.getName().substring(1));
					Method method = geometry.getClass().getMethod(methodName);
					if (method.invoke(geometry) != null) {
						VALUES(field.getName(), "#{" + field.getName() + "}");
					}
				}
				VALUES("SHAPE",
						"SDE.ST_GEOMETRY(#{wkt,typeHandler=com.zifan.st_geometry.handler.STGeometryHandler}, #{srId})");
				VALUES("OBJECTID", "#{objectId}");
			}

		}.toString();
	}

这个方法可以根据继承STGeometry类的类动态返回插入图形数据的sql语句。

mybatis的Mapper接口方法实现

    final static String GET_NEXT_OBJECTID_SQL = "SELECT SDE.VERSION_USER_DDL.NEXT_ROW_ID(UPPER(#{owner,typeHandler=com.zifan.st_geometry.handler.DBOwnerHandler}),(SELECT REGISTRATION_ID FROM SDE.TABLE_REGISTRY WHERE TABLE_NAME = UPPER(#{tableName}) AND OWNER = UPPER(#{owner,typeHandler=com.zifan.st_geometry.handler.DBOwnerHandler}))) AS OBJECTID FROM DUAL";

    @SelectKey(statement = GET_NEXT_OBJECTID_SQL, keyProperty = "objectId", before = true, resultType = long.class)
	@InsertProvider(type = STGeomertySqlBuilder.class, method = "buildInsertSql")
	void saveGeometryToTable(STGeometry object);

SelectKey注解主要进行插入数据前先查找下个OBJECTID值。其中上面涉及到一个TypeHandler,主要用户获取表默认所在的数据库用户名

package com.zifan.st_geometry.handler;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeHandler;

public class DBOwnerHandler implements TypeHandler<String> {

	public void setParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
		// TODO Auto-generated method stub
		if (parameter == null) {
			parameter = ps.getConnection().getMetaData().getUserName();
		}
		ps.setString(i, parameter);
	}

	public String getResult(ResultSet rs, String columnName) throws SQLException {
		// TODO Auto-generated method stub
		return null;
	}

	public String getResult(ResultSet rs, int columnIndex) throws SQLException {
		// TODO Auto-generated method stub
		return null;
	}

	public String getResult(CallableStatement cs, int columnIndex) throws SQLException {
		// TODO Auto-generated method stub
		return null;
	}

}

测试

先来创建一个STGeometry子类,这里有两个属性对应的是数据库的字段。

package com.zifan.st_geometry.model;

public class SubGeometry extends STGeometry {

	private String ysdm;
	private String djth;

	public String getYsdm() {
		return ysdm;
	}

	public void setYsdm(String ysdm) {
		this.ysdm = ysdm;
	}

	public String getDjth() {
		return djth;
	}

	public void setDjth(String djth) {
		this.djth = djth;
	}
}

测试方法

    @Test
	public void testInsert() {
		String shortWkt = "POLYGON ((3 3, 4 6, 5 3, 3 3))";
		SubGeometry czdj = new SubGeometry();
		czdj.setDjth("长");
		czdj.setYsdm("华");
		czdj.setWkt(shorWkt);
		czdj.setSrId(2);
		czdj.setTableName("CZDJ2");
		stGeometryMapper.saveGeometryToTable(czdj);
		Assert.assertEquals(6, czdj.getObjectId());

	}

执行后存储的图形数据djth和ysdm两个属性是存在值的。

至此通过mybatis利用st_geometry就完成了对arcgis图形数据的叠加分析和存储。

以上涉及到的mybatis的使用可以查看其API,此外是通过spring-boot与mybatis结合进行的开发测试。有兴趣可以查看一下关于spring-boot的更多知识。

工程代码见码云通过spring-boot+mybatis+swagger构建。

 

© 著作权归作者所有

共有 人打赏支持
翻

粉丝 3
博文 28
码字总数 11162
作品 0
东莞
利用st_geometry进行图形叠加分析

首先看一下st_geometry进行图形叠加分析语句: 该语句表示的是SOURCETABLE 表中OBEJCTID=18133的图形数据与TARGETTABLE 表中所有的图形数据进行叠加,最终返回的是存在叠加目标表(TARGETTAB...

2016/11/18
151
0
PostgreSQL 实时位置跟踪+轨迹分析系统实践 - 单机顶千亿轨迹/天

标签 PostgreSQL , PostGIS , 动态更新位置 , 轨迹跟踪 , 空间分析 , 时空分析 背景 随着移动设备的普及,越来越多的业务具备了时空属性,例如快递,试试跟踪包裹、快递员位置。例如实体,具...

德哥
01/02
0
0
简析服务端通过GT导入SHP至PG的方法

文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景 项目中需要在浏览器端直接上传SHP后服务端进行数据的自动入PG库以及发布至geoserv...

李晓晖
2016/11/24
0
0
PostgreSQL+PostGIS 的使用

阅读目录 一、PostGIS中的几何类型 二、 PostGIS中空间信息处理的实现 三、 PostGIS中的常用函数 四、 PostGIS示例 回到顶部 一、PostGIS中的几何类型 PostGIS支持所有OGC规范的“Simple Fe...

技术mix呢
2017/11/07
0
0
postgis常用函数(99%转载 1%原创)

1,基本操作函数 AddGeometryColumn(<schemaname>, <tablename>, <columnname>, <srid>, <type>, <dimension>) 给一个已存在属性数据表增加一个几何字段(geomtry column)。schemaname 指表的模......

威武不能笑
2013/01/07
0
0
C#进行Visio二次开发之Visio模具制作(2)

Visio二次开发开发过程中,模具制作也是其中一项有比较细致,技术含量高的工作来的,要做好一个不错的模具,需要了解不少Visio的开发资料以及制作技巧。 在前面一篇《C#进行Visio二次开发之V...

长平狐
2012/06/11
244
0
C#进行Visio二次开发之Visio模具制作(2)

Visio二次开发开发过程中,模具制作也是其中一项有比较细致,技术含量高的工作来的,要做好一个不错的模具,需要了解不少Visio的开发资料以及制作技巧。 在前面一篇《C#进行Visio二次开发之V...

长平狐
2012/08/22
73
0
配置Oracle访问SQL地理数据库

Oracle访问空间数据 ArcSDE是ArcGIS的空间数据引擎,它是在关系数据库管理系统(RDBMS)中存储和管理多用户空间数据库的通路。以前连接方式有两种,服务连接与直接连接(简称"直连"),两种在...

gisweis
2017/11/23
0
0
c#中关于arcgis的ITopologicalOperator接口的问题

利用c# 写了一个控制台程序,其中的一个功能想利用ITopologicalOperator接口中的Difference方法,想获得原始图形除去相交部分之外的图形部分。 代码如下: ITopologicalOperator pTopologica...

小wei
2014/09/12
322
1
Oracle空间查询 ORA-28595

可使用数据库管理系统 (DBMS) 的结构化查询语言 (SQL)、数据类型和表格式来处理地理数据库或安装了 ST_Geometry 类型的数据库中所存储的信息。 例如,在ArcMap中我们使用"相交"工具进行空间操...

gisweis
2017/04/24
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

JavaEE——JavaScript

声明:本栏目所使用的素材都是凯哥学堂VIP学员所写,学员有权匿名,对文章有最终解释权;凯哥学堂旨在促进VIP学员互相学习的基础上公开笔记。 JavaScript 内置对象 String对象方法: date对象...

凯哥学堂
9分钟前
0
0
Git 远程代码回滚master

方式一(推荐): git revert commit-id 方式二(不推荐):不推荐原因:推送到线上后,其它开发人员需要重新clone git reset --hard commit-id git push origin HEAD --force...

浮躁的码农
9分钟前
0
0
Elasticesearch学习(7)—— ES查询与Java API的对应关系

1、普通查询 类型 ES查询语句 Java查询实现 结果 查询格式 { "query": { "bool": { "must": [], "must_not": [], "should": [], "filter": [] } }, "from": 0, "size": 10, "sort": [] } Que......

叶枫啦啦
10分钟前
4
0
getElementsByClassName()与getElementById()区别

1.document.getElementsByClassName() 返回的是数组 使用:document.getElementsByClassName("className")[0].innerText='具体内容' 2.document.getElementById() 返回的是单个元素 使用:d......

botkenni
20分钟前
0
0
MyBatis入门

一、安装 <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>x.x.x</version></dependency> 二、从 XML 中构建 SqlSessionFactory String r......

一个yuanbeth
21分钟前
0
0
聊聊spring cloud的LoadBalancerAutoConfiguration

序 本文主要研究一下spring cloud的LoadBalancerAutoConfiguration RibbonAutoConfiguration spring-cloud-netflix-ribbon-2.0.0.RC2-sources.jar!/org/springframework/cloud/netflix/ribb......

go4it
24分钟前
0
0
【转】使用Lombok来优雅的编码

前言 Lombok 是一种 Java™ 实用工具,可用来帮助开发人员消除 Java 的冗长,尤其是对于简单的 Java 对象(POJO)。它通过注解实现这一目的。 正文 添加依赖 在 pom.xml 文件中添加相关依赖:...

HAVENT
26分钟前
0
0
Dubbo 源码解读 —— 可支持序列化及自定义扩展

一、概述 从源码中,我们可以看出来。目前,Dubbo 内部提供了 5 种序列化的方式,分别为 fastjson、Hessian2、Kryo、fst 及 Java原生支持的方式 。 针对不同的序列化方式,对比内容如下: 名...

Ryan-瑞恩
33分钟前
0
0
MySQL内存设置—— MySQL server has gone away

set global max_allowed_packet=268435456

一梦心草
43分钟前
0
0
推导式

列表、集合和字典推导式 列表推导式是Python最受喜爱的特性之一。它允许用户方便的从一个集合过滤元素,形成列表,在传递参数的过程中还可以修改元素。形式如下: [expr for val in collect...

火力全開
48分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部