MySQL空间扩展支持几何数据的存储,生成,分析,优化。MySQL支持以下数据类型:Geometry:可以存储所有的几何类型;Point:简单点;LINESTRING:简单线;POLYGON:简单面;MULTIPOINT:多点;MULITILINESTRING:多线;MUILITIPOLYGON:很多方面;GEOMETRYCOLLECTION:任何几何集合。在创建表的时候可以根据需求选择合适的几何类型存储你的空间数据。
Geometry主要相关类
Geometry是所有此扩展中类型得基类,其他类型如Point,LineString,Polygon都是Geometry的子类。Geometry有一些属性,这些属性是所有其他几何类的共有属性:
type: 类型(Point, LineString,...)
SRID: 该值确定了用于描述定义几何对象的坐标空间的空间坐标系统,参考链接:
coordinates: 坐标值
interior, boundary, exterior: interior是几何对象所展空间的部分,boundary是几何对象的边界,exterior是几何对象未占有的空间。
MBR: 能够覆盖几何对象的最小矩形,可以想象成信封,它由几何对象中最大最小的坐标值组合而成:((MINX MINY, MAXX MINY, MAXX MAXY, MINX MAXY, MINX MINY))
simple/nonsimple: 几何对象是否简单
closed/not closed: 几何对象是否封闭
dimension: 维度数(Point: 0, LineString: 1, Polygon: 2)
MySQL插入和查询数据
1、创建一个带有空间索引的表
我这里主要是用于检索遥感影像数据的,这里就只创建了两个字段,一个是uuid字段 id,一个是存储空间数据的字段address_latlon。
CREATE TABLE `xxxx_table` (
`id` varchar(512) NOT NULL,
`address_latlon` geometry NOT NULL,
PRIMARY KEY (`id`),
SPATIAL KEY `address_latlon` (`address_latlon`)
) ;
这里创建好之后,就可以往里面插入数据了。
2、插入数据
数据的插入和普通的数据插入一样,只是geometry数据需要使用st_geomfromtext等函数来构造,相关的文档参考在这里gis-data-formats还有这个populating-spatial-columns。
这里只展示一个简单数据插入,这里我使用的是单多边形,只有四个点(逆时针顺序),使用WKT描述几何数据。
insert into gim (path,box) values('%s',ST_GeomFromText('Polygon((116.18866 39.791107, 116.124115 39.791107, 116.18866 39.833679, 116.124115 39.833679, 116.18866 39.791107))'));
3、查询数据
查询这里和普通的查询也一样,只是where字句后面使用空间过滤相关选项就是。使用空间索引进行查询的相关文档在这里using-spatial-indexes 。
MySQL的文档中只提及了MBRContains和MBRWithin两种方式,经过测试,MBRIntersects、MBREqual、MBROverlaps、MBRTouches、MBRDisjoint都可以使用。
SpatiaLite中有一幅关于空间检索的图,放在这里做个参考。SpatiaLite有一篇详细介绍空间索引的文档,链接在这里:http://www.gaia-gis.it/spatialite-2.1/SpatiaLite-manual.html
一个简单的查询示例:
select * from xxxx_table where MBRContains(st_geomfromtext('polygon((116.438599 39.832306, 116.374054 39.832306, 116.438599 39.876251, 116.374054 39.876251, 116.438599 39.832306))'),address_latlon);
mysql空间函数汇总
名称 | 描述 |
ST_StartPoint() | LineString的起始点 |
ST_EndPoint() | LineString的终点 |
ST_Transform() | 变换几何的坐标 |
ST_GeoHash() | 产生geohash值 |
ST_LongFromGeoHash() | 从geohash值返回经度 |
ST_LatFromGeoHash() | 从geohash值返回纬度 |
ST_GeomFromGeoJSON() | 从GeoJSON对象生成几何 |
Polygon() | 从LineString参数构造多边形 |
ST_PointN() | 从LineString返回第N个点 |
MultiLineString() | 从LineString值构造MultiLineString |
LineString() | 从Point值构造LineString |
MultiPoint() | 从Point值构造MultiPoint |
MultiPolygon() | 从Polygon值构造MultiPolygon |
ST_GeomFromWKB(), ST_GeometryFromWKB() | 从WKB返回几何 |
ST_GeomCollFromWKB(), ST_GeometryCollectionFromWKB() | 从WKB返回几何集合 |
ST_LineFromWKB(), ST_LineStringFromWKB() | 从WKB构造LineString |
ST_MLineFromWKB(), ST_MultiLineStringFromWKB() | 从WKB构造MultiLineString |
ST_MPointFromWKB(), ST_MultiPointFromWKB() | 从WKB构造MultiPoint |
ST_MPolyFromWKB(), ST_MultiPolygonFromWKB() | 从WKB构造MultiPolygon |
ST_PointFromWKB() | 从WKB构造点 |
ST_PolyFromWKB(), ST_PolygonFromWKB() | 从WKB构造多边形 |
ST_GeomFromText(), ST_GeometryFromText() | 从WKT返回几何 |
ST_GeomCollFromText(),ST_GeometryCollectionFromText(),ST_GeomCollFromTxt() | 从WKT返回几何集合 |
ST_PointFromText() | 从WKT构建点 |
ST_LineFromText(), ST_LineStringFromText() | 从WKT构造LineString |
ST_MLineFromText(), ST_MultiLineStringFromText() | 从WKT构造MultiLineString |
ST_MPointFromText(), ST_MultiPointFromText() | 从WKT构造MultiPoint |
ST_MPolyFromText(), ST_MultiPolygonFromText() | 从WKT构造MultiPolygon |
ST_PolyFromText(), ST_PolygonFromText() | 从WKT构造多边形 |
springboot存储空间数据
pom.xml文件配置
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-spatial</artifactId>
</dependency>
application.propertie引入mysql方言配置
spring.jpa.properties.hibernate.dialect=org.hibernate.spatial.dialect.mysql.MySQL56InnoDBSpatialDialect
实体类指定Geometry类型
@Column(name = "address_latlon",columnDefinition = "GEOMETRY")
private Geometry addresslatlon;
通过方式保存数据
XxxPointDTO xxxPointDTO = new XxxPointDTO();
WKTReader reader = new WKTReader();
Geometry geom = null;
try {
geom = reader.read("POLYGON((115 25, 115 15, 125 15, 125 25, 115 25))");
} catch (ParseException e) {
e.printStackTrace();
}
xxxPointDTO.setAddressLatlon((com.vividsolutions.jts.geom.Polygon) geom);
xxxPointDAO.save(xxxPointDTO);
springboot查询空间数据
现在使用到的情况有两种,一种是原生SQL方式,上面已经描述。还有一种通过jap查询的方式。
Sort sort = Sort.by(Sort.Direction.DESC,"addressLatlon");
Pageable pageable = PageRequest.of(0,10,sort);
Page<XxxPointDTO> page = xxxPointDAO.findAll((root,query,cb) -> {
List<Predicate> predicates = new ArrayList<>();
Expression<String> findInSetFun = cb.function("MBRIntersects", String.class,cb.function("st_geomfromtext", String.class,cb.literal(params)),root.get("addressLatlon"));
predicates.add(cb.greaterThan(findInSetFun, ""));
return cb.and(predicates.toArray(newPredicate[predicates.size()]));
},pageable);
return PageUtils.getPageMap(page);