Postgis关于Point类型的一些查询操作

本文详细介绍如何使用PostGIS进行点类型的创建与查询操作,包括多种创建点的方式、坐标系设置、坐标读取及转换等内容。

本文着重介绍Point类型的查询操作,以下操作均为二维,不讨论三维数据。

  • 创建点

      点的WKT表述如POINT(116.39088 39.90763),在Postgis中创建一个点几个方式:

ST_Point、ST_MakePoint:

--用法:ST_Point(float x_lon, float y_lat);
--输出:0101000000452A8C2D04195D402A6F47382DF44340
SELECT ST_Point(116.39088,39.90763)

      上面虽然创建了点,但是SRID却是0(unknown),可以通过ST_SRID查看。下面方式设置坐标系为4326:

--用法:ST_Point(float x_lon, float y_lat);
--输出:0101000020E6100000452A8C2D04195D402A6F47382DF44340
SELECT ST_SetSRID(ST_Point(116.39088,39.90763),4326)

      坐标顺序是经度(或x)在前,纬度(或y)在后。ST_MakePoint和ST_Point一样,ST_MakePoint可以快速高效的创建一个点。

ST_GeometryFromText、ST_PointFromText:

--用法1:geometry ST_GeometryFromText(text WKT);
--用法2:geometry ST_GeometryFromText(text WKT, integer srid);
--输出:0101000020E6100000452A8C2D04195D402A6F47382DF44340
SELECT ST_GeomFromText('POINT(116.39088 39.90763)',4326);

      ST_GeometryFromText和ST_GeomFromText一样,根据WKT描述的对象返回一个具体的geometry对象,WKT可以是POLYGON、MULTIPOLYGON、LINESTRING等。在这里它是一个点。如果要指明创建一个点,可以用ST_PointFromText:

--用法1:geometry ST_PointFromText(text WKT);
--用法2:geometry ST_PointFromText(text WKT, integer srid);
--输出:0101000020E6100000452A8C2D04195D402A6F47382DF44340
SELECT ST_PointFromText('POINT(116.39088 39.90763)',4326);

      未指定srid时,创建的geomtry默认的srid是0。

ST_GeomFromGML、ST_GMLToSQL:

--geometry ST_GeomFromGML(text geomgml);
--geometry ST_GeomFromGML(text geomgml, integer srid);
--输出:0101000020E6100000452A8C2D04195D402A6F47382DF44340
SELECT ST_GeomFromGML('
    <gml:Point srsName="EPSG:4326">
    	<gml:coordinates>116.39088,39.90763</gml:coordinates>
    </gml:Point>
');

      属性srsName会被读取。也可以在参数中指定srid:

SELECT ST_GeomFromGML('
    <gml:Point>
	<gml:coordinates>116.39088,39.90763</gml:coordinates>
    </gml:Point>
',4326);

     ST_GeomFromGML参数geomgml只能是GML的geometry部分,不是整个GML文档。目前支持 GML 2.1.2、 3.1.1、 3.2.1等版本。ST_GMLToSQL是ST_GeomFromGML的别名,用法一样:

--输出:0101000020E6100000452A8C2D04195D402A6F47382DF44340
SELECT ST_GMLToSQL('
    <gml:Point>
	<gml:coordinates>116.39088,39.90763</gml:coordinates>
    </gml:Point>
',4326);

ST_GeomFromGeoJSON:

--geometry ST_GeomFromGeoJSON(text geomjson);
--输出:0101000020E6100000452A8C2D04195D402A6F47382DF44340
SELECT ST_SetSRID(ST_GeomFromGeoJSON('{
    "type":"Point",
    "coordinates":[116.39088,39.90763]
}'),4326);

      与ST_GeomFromGML一致,参数geomjson只能是geometry描述。ST_GeomFromGeoJSON没有srid参数,而标准GeoJSON geometry对象中不含坐标系,所以需要ST_SetSRID用设置坐标系。 

ST_GeomFromKML:

--geometry ST_GeomFromKML(text geomkml);
--输出:0101000020E6100000452A8C2D04195D402A6F47382DF44340
SELECT ST_SetSRID(ST_GeomFromKML('
    <Point>
        <coordinates>116.39088,39.90763</coordinates>
    </Point>
'),4326);

      和ST_GeomFromGeoJSON一致,参数geomkml只能是geometry描述。ST_GeomFromGeoJSON没有srid参数,所以需要ST_SetSRID用设置坐标系。

      其他还有一些二进制、EWKT的读取类似,这里不做介绍。

  • 输出

ST_X、ST_Y、ST_Z等:

--float ST_X(geometry a_point);
--输出:116.39088
SELECT ST_X(ST_GeomFromText('POINT(116.39088 39.90763)',4326));
--输出:Null
SELECT ST_Z(ST_GeomFromText('POINT(116.39088 39.90763)',4326));

      a_point是一个POINT对象,ST_X输出X坐标。

GeometryType:

--text GeometryType(geometry geomA);
--输出:POINT
SELECT GeometryType(ST_GeomFromText('POINT(116.39088 39.90763)',4326));
ST_GeometryType:
--text ST_GeometryType(geometry g1);
--输出:ST_Point
SELECT ST_GeometryType(ST_GeomFromText('POINT(116.39088 39.90763)',4326));

ST_FlipCoordinates交换X和Y坐标:

--geometry ST_FlipCoordinates(geometry geom);
--输出:POINT(39.90763 116.39088)
SELECT ST_AsText(ST_FlipCoordinates(ST_GeomFromText('POINT(116.39088 39.90763)',4326)))
--输出:POINT ZM (39.90763 116.39088 3 6)
SELECT ST_AsText(ST_FlipCoordinates(ST_GeomFromText('POINT(116.39088 39.90763 3 6)',4326)))

      除了POINT外,还支持其他的LINESTRING等。

ST_Transform坐标转换:

--4326转4490。4326与4490都是地理坐标系,坐标系差异很小,所以转出的该点差别小
--输出:POINT(116.39088 39.90763)
-- SELECT ST_AsText(ST_Transform(ST_GeomFromText('POINT(116.39088 39.90763)',4326),4490))

--4326转3857。投影
--输出:POINT(12956573.494581 4852528.38789462)
SELECT ST_AsText(ST_Transform(ST_GeomFromText('POINT(116.39088 39.90763)',4326),3857))

其他

--输出:{"type":"Point","coordinates":[116.39088,39.90763]}
SELECT ST_AsGeoJSON(ST_GeomFromText('POINT(116.39088 39.90763)',4326));

--输出:<Point><coordinates>116.39088,39.907629999999997</coordinates></Point>
SELECT ST_AsKML(ST_GeomFromText('POINT(116.39088 39.90763)',4326));

--输出:<gml:Point srsName="EPSG:4326"><gml:coordinates>116.39088,39.907629999999997</gml:coordinates></gml:Point>
SELECT ST_AsGML(ST_GeomFromText('POINT(116.39088 39.90763)',4326));

--输出:POINT(116.39088 39.90763)
SELECT ST_AsText(ST_GeomFromText('POINT(116.39088 39.90763)',4326));

--integer ST_CoordDim(geometry geomA);
--输出:2
SELECT ST_CoordDim(ST_GeomFromText('POINT(116.39088 39.90763)',4326));
以上就是一些关于POINT的WKT操作。



<think>嗯,用户这次的问题很具体,直接询问如何在SpringBoot中操作PostGIS实现点查询。看来用户已经跳过了环境搭建阶段,直接进入核心功能开发环节。从ta的提问方式看,应该是有些Java和Spring基础的技术人员,但可能不熟悉GIS相关的技术栈。回顾之前的对话历史,我注意到系统要求生成相关问题。用户当前的查询是关于点查询实现,后续可能会延伸出其他GIS操作需求。上次提供的引用材料里包含GeoTools对PostGIS的支持说明,虽然用户说“不是真正的需求”,但这个技术栈确实能用上。用户明确要求“实现点查询”,但具体是空间范围查询还是最近邻查询呢?考虑到常见场景,我选择以半径范围查询为示例,这比简单的点检索更实用。HibernateSpatial方案是首选,因为它在SpringBoot中集成最流畅,用户的学习成本也低。如果用户后续需要更专业的GIS功能,再考虑引入GeoTools方案。PostGISPoint类型处理容易踩坑,需要专门提醒:1)WKT格式必须用POINT(xy)写法2)SRID不能遗漏这些细节在普通数据库操作里不会遇到,但对GIS系统却是关键。测试数据准备也要专门说明,因为地理数据的录入方式特殊。用户可能习惯用普通insert语句,但这里必须用ST_GeomFromText函数换坐标点。考虑到用户后续可能的需求,预留了扩展方向:-不同空间关系查询(如多边形内点查询)-优化索引建议-坐标换说明这些扩展点都设计成可以在“相关技术”部分自然延伸。特别是坐标参考系问题,很多初学者会在使用不同坐标的数据源时遇到定位偏移问题。</think> 在Spring Boot中操作PostGIS数据库实现点查询,需要整合**Spring Data JPA**和**Hibernate Spatial**库。以下是实现步骤和代码示例: --- ### **1. 核心依赖** 在`pom.xml`中添加: ```xml <!-- Spring Data JPA --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <!-- PostGIS Driver --> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> </dependency> <!-- Hibernate Spatial --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-spatial</artifactId> </dependency> ``` --- ### **2. 配置数据库连接** `application.properties`: ```properties spring.datasource.url=jdbc:postgresql://localhost:5432/your_db_name spring.datasource.username=your_username spring.datasource.password=your_password spring.jpa.database-platform=org.hibernate.spatial.dialect.postgis.PostgisDialect ``` --- ### **3. 实体类映射地理坐标** ```java import org.locationtech.jts.geom.Point; import javax.persistence.*; @Entity public class Location { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; @Column(columnDefinition = "geometry(Point,4326)") // 使用WGS84坐标系 private Point geom; // 存储经纬度点 // Getters & Setters } ``` --- ### **4. 仓库接口定义查询** ```java import org.locationtech.jts.geom.Point; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; public interface LocationRepository extends JpaRepository<Location, Long> { // 示例1:查询指定半径内的所有点 (单位:米) @Query("SELECT l FROM Location l WHERE ST_DWithin(l.geom, :center, :radius) = true") List<Location> findWithinRadius(@Param("center") Point center, @Param("radius") double radius); // 示例2:查询指定矩形范围内的点 @Query("SELECT l FROM Location l WHERE l.geom && ST_MakeEnvelope(:minX, :minY, :maxX, :maxY, 4326)") List<Location> findWithinBoundingBox(@Param("minX") double minX, @Param("minY") double minY, @Param("maxX") double maxX, @Param("maxY") double maxY); } ``` --- ### **5. 服务层与控制器** **服务层实现**: ```java @Service public class LocationService { private final LocationRepository repo; private final GeometryFactory geometryFactory = new GeometryFactory(); public LocationService(LocationRepository repo) { this.repo = repo; } // 查询5km范围内的点 public List<Location> findNearbyPlaces(double lat, double lng) { Point center = geometryFactory.createPoint(new Coordinate(lng, lat)); // 注意:坐标顺序为(x=lng, y=lat) center.setSRID(4326); // 必须设置SRID! return repo.findWithinRadius(center, 5000); } } ``` **控制器示例**: ```java @RestController @RequestMapping("/locations") public class LocationController { private final LocationService service; public LocationController(LocationService service) { this.service = service; } @GetMapping("/nearby") public List<Location> getNearby(@RequestParam double lat, @RequestParam double lng) { return service.findNearbyPlaces(lat, lng); } } ``` --- ### **6. 创建空间索引(提升性能)** 在PostGIS中执行SQL: ```sql CREATE INDEX idx_location_geom ON location USING GIST (geom); ``` --- ### **关键注意事项** 1. **坐标系一致性**: 确保数据库中的点、查询输入点使用相同的SRID(如`4326`)[^1]。 2. **坐标顺序**: JTS库中`Point`的坐标格式为`(x=lng, y=lat)`。 3. **单位换算**: `ST_DWithin`函数默认使用**米**,若使用地理坐标(4326),需启用球面计算: ```sql SET postgis.enable_spheroid = true; ``` --- ### **测试数据插入示例** ```sql INSERT INTO location (name, geom) VALUES ('Central Park', ST_GeomFromText('POINT(-73.968285 40.785091)', 4326)); ``` --- ### **相关技术** - **Hibernate Spatial**:封装了PostGIS的空间函数(如`&&`, `ST_DWithin`)[^1] - **PostgisDialect**:使Hibernate支持地理数据类型 - **GeometryFactory**:动态构建JTS几何对象 [^1]: GeoTools提供插件支持多种数据库空间扩展(如PostGIS),但Hibernate Spatial更适合Spring Boot集成。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值