Mybatis操作postgresql的postgis的一些总结

Mybatis操作postgresql的postgis的一些总结

1、springboot项目连接postgresql数据库

导入postgresql的依赖

xml 复制代码
   <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
     </dependency>

导入mybatisplus的依赖

xml 复制代码
    <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
            <version>3.5.7</version>
        </dependency>

数据库连接池依赖

xml 复制代码
<dependency>  
  <groupId>com.zaxxer</groupId>  
  <artifactId>HikariCP</artifactId>  
</dependency>

配置yml文件中postgresql的连接 ==连接的URL要说明数据库名称和选择的架构==

yml 复制代码
# 数据源配置  
spring:  
  datasource:  
    # 数据库连接URL要说明数据库名称和选择的架构  
    url: jdbc:postgresql://localhost:5432/postgis_35_sample?currentSchema=public  
    # 数据库用户名  
    username: postgres  
    # 数据库密码  
    password: 123456  
    # 数据库驱动类名  
    driver-class-name: org.postgresql.Driver  
    # 指定数据源类型(这里使用 HikariCP 连接池)  
    type: com.zaxxer.hikari.HikariDataSource  
    # HikariCP 连接池配置  
    hikari:  
      # 连接池的名称,方便在监控工具中识别  
      pool-name: PostGISPool  
      # 最小空闲连接数,建议设置为10-30%的最大连接池大小  
      minimum-idle: 10  
      # 最大连接池大小,根据应用并发量和数据库负载调整  
      maximum-pool-size: 30  
      # 是否启用自动提交,true为启用(默认值)  
      auto-commit: true  
      # 获取连接的超时时间(毫秒),增加到60秒以应对可能的网络延迟  
      connection-timeout: 60000 # 60 seconds  
      # 连接验证的超时时间(毫秒)  
      validation-timeout: 30000 # 30 seconds  
      # 连接的最大生命周期(毫秒),避免长时间占用连接  
      max-lifetime: 1800000 # 30 minutes  
      # 获取连接后执行的 SQL 语句,用于验证连接是否有效  
      connection-init-sql: SELECT 1  
      # 连接泄漏检测时间(毫秒),可帮助发现连接未关闭的情况  
      leak-detection-threshold: 30000 # 30 seconds  
      # 是否注册JMX MBeans,方便通过JMX监控连接池状态  
      register-mbeans: true  

# MyBatis Plus 配置  
mybatis-plus:  
  # 将执行的 SQL 语句和相关信息打印到标准输出(如控制台)  
  configuration:  
    # 启用 MyBatis 的日志输出  
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl  
  # 指定 MyBatis POJO 类所在的包  
  type-aliases-package: com.postgis.pojo  
  # 全局配置  
  global-config:  
    # 数据库配置  
    db-config:  
      # 设置 ID 生成策略为自增  
      id-type: AUTO  
  # 指定 Mapper XML 文件的扫描路径  
  mapper-locations: classpath*:mapper/**/*.xml  

# 日志配置  
logging:  
  # 配置日志级别  
  level:  
    # 设置 com.postgis 包下的日志级别为 DEBUG,方便调试  
    com.postgis: debug

2、关于postgis数据库表映射的实体类的相关配置

  • ==一定要有一个geom字段==映射到postgis的geomtry字段,==x、y坐标在数据库表中没有映射的字段,但是可以从geom字段中解析出来==
  • ==不要使用Lombok注解==提供的getter和setter方法,会出现bug
java 复制代码
/**  
 * 这是一个数据传输对象(Data Transfer Object, DTO),用于映射数据库表 "locations" 中的数据。  
 * 该类提供了与数据库表 "locations" 中字段相对应的 Java 属性,并通过注解定义了它们之间的映射关系。  
 */  
@TableName(value = "locations")  
public class Location{  
    @TableId  
    private Integer id;   
    private String name;  
    /**  
     * 存储几何位置的几何数据。  
     * 通常用于存储空间坐标信息,如点、线、面等。  
     * 在 PostGIS 中,可能使用 geometry 类型来存储。  
     */  
    private String geom;  
    // x、y坐标在数据库表中没有映射的字段,但是可以从geom字段中解析出来
    /**  
     * X 坐标
     */  
    @TableField(exist = false)
    private double xCoord;  
    /**  
     * Y 坐标
     */  
    @TableField(exist = false)
    private double yCoord;  
    // Getters 和 Setters 方法(不要使用lombok,会出问题)  
  ......
  }

3、Mapper层sql语句中关于geometry字段映射的注意事项

SQL语句中常用的将WKB类型转为Java可以表示的类型的函数

ST_AsText (geometry):将几何对象转换为WKT格式。(string类型) ST_AsGeoJSON (geometry):将几何对象转换为GeoJSON格式。(string类型) ST_X(point) :返回点的X坐标 (返回double类型)。 ST_Y(point):返回点的Y坐标 (返回double类型)。

一、 映射所有字段不要使用select * from db,要把所要的字段写出来,同时==关于geometry类型的字段要使用AS指定为实体类==中的字段名称。

java 复制代码
@Select("SELECT id, name, ST_X(geom) AS x_coord, ST_Y(geom) AS y_coord, ST_AsGeoJSON(geom) AS geom FROM locations WHERE id = #{id};")
Location findGeoJsonById(Long id);

查询结果

json 复制代码
{"id":13,"name":"Location D","geom":"{\"type\":\"Point\",\"coordinates\":[116.3974,39.984]}","xCoord":0.0,"yCoord":0.0}

二、直接使用String类型接收geom字段的WKB值

java 复制代码
@Select("SELECT id, name, geom FROM locations WHERE id = #{id}")
Location findGeoJsonById(Long id);

返回值

json 复制代码
{"id":11,"name":"Location B","geom":"0101000020E6100000F1A0D9756F195D4032207BBDFBFD4340","xCoord":0.0,"yCoord":0.0}

根据返回值可见,string类型的geom字段存储了wkb十六进制数据,对此 ==Java的GeoTools可以提供强大的方法解析wkb十六进制数据==。

4、GeoTools解析WKB数据为geojson数据

GeoTools主要功能

1、数据访问:

支持多种地理数据格式,如 Shapefile、GeoJSON、KML、GML、PostGIS 等。 可以从不同来源读取和写入地理数据,包括数据库和文件系统。

2、空间分析:

提供几何操作和空间分析功能,允许用户执行缓冲区、重投影、空间查询等操作。

3、地图渲染:

具有强大的渲染和符号化功能,可以创建地图图层,并根据所需样式动态渲染地理数据。

4、支持标准:

遵循 OGC(开放地理空间联盟)标准,支持各种网络服务功能(如 WMS 和 WFS)。 能够与其他 GIS 组件(如 GeoServer)无缝集成。 aliyunmaven * 阿里云公共仓库 maven.aliyun.com/repository/...

添加将WKB 字符串转换为GeoJSON 格式的工具类

1、配置依赖

需要改自己 maven 的镜像源配置如下:

xml 复制代码
    <mirror> 
      <id>alimaven</id> 
      <name>aliyun maven</name> 
      <url>http://maven.aliyun.com/nexus/content/groups/public/</url> 
      <mirrorOf>*,!osgeo,!maven2-repository.dev.java.net,!boundless</mirrorOf> 
    </mirror>

需要添加 repository如下: (与dependencies标签同一级别)

xml 复制代码
<repositories>
       <repository>
           <id>osgeo</id>
           <name>OSGeo</name>
           <url>https://repo.osgeo.org/repository/release/</url>
       </repository>
   </repositories>

之后就可以成功导入geotools的依赖了,注意消除依赖冲突 消除依赖冲突的方法

xml 复制代码
<dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-main</artifactId>
            <version>24.0</version>
            <exclusions>
                <exclusion>
                    <groupId>tech.units</groupId>
                    <artifactId>indriya</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>si.uom</groupId>
                    <artifactId>si-quantity</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-geojson</artifactId>
            <version>24.0</version>
        </dependency>
2、添加工具类

在utils包下新建将WKB 字符串转换为 GeoJSON格式数据(Map<String, Object>)的工具类

java 复制代码
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.geotools.geojson.geom.GeometryJSON;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.io.ParseException;
import org.locationtech.jts.io.WKBReader;

import java.io.IOException;
import java.io.StringWriter;
import java.util.Map;

@Slf4j
public class WKBToGeoJSONUtil {

    /**
     * 将WKB十六进制字符串转换为GeoJSON格式的Map
     * @param hexWKB PostGIS返回的WKB十六进制字符串
     * @param decimals 保留的小数位数
     * @return 对应GeoJSON结构的Map
     * @throws Exception 如果解析WKB或生成GeoJSON时发生错误
     */
    public static Map<String, Object> convert(String hexWKB, int decimals) throws Exception {
        // 解析WKB字符串为JTS Geometry对象
        Geometry geometry = parseWKB(hexWKB);
        // 将Geometry对象转换为GeoJSON Map
        return convertToGeoJSONMap(geometry, decimals);
    }

    /**
     * 解析WKB字符串为JTS Geometry对象
     * @param hexWKB WKB十六进制字符串
     * @return 解析后的Geometry对象
     * @throws Exception 如果解析WKB时发生错误
     */
    private static Geometry parseWKB(String hexWKB) throws Exception {
        try {
            // 创建WKBReader实例
            WKBReader wkbReader = new WKBReader();
            // 将十六进制字符串转换为字节数组
            byte[] wkbBytes = WKBReader.hexToBytes(hexWKB);
            // 解析字节数组为Geometry对象
            return wkbReader.read(wkbBytes);
        } catch (ParseException e) {
            // 如果解析失败,记录错误并抛出异常
            log.error("Failed to parse WKB string: {}", hexWKB, e);
            throw new Exception("Failed to parse WKB string", e);
        }
    }

    /**
     * 将Geometry对象转换为GeoJSON Map
     * @param geometry JTS Geometry对象
     * @param decimals 保留的小数位数
     * @return GeoJSON格式的Map
     * @throws IOException 如果生成GeoJSON时发生错误
     */
    private static Map<String, Object> convertToGeoJSONMap(Geometry geometry, int decimals) throws IOException {
        try {
            // 创建GeometryJSON实例,指定小数位数
            GeometryJSON geometryJSON = new GeometryJSON(decimals);
            // 使用StringWriter生成GeoJSON字符串
            StringWriter writer = new StringWriter();
            geometryJSON.write(geometry, writer);
            String geoJsonStr = writer.toString();

            // 使用Jackson将GeoJSON字符串转换为Map
            ObjectMapper objectMapper = new ObjectMapper();
            return objectMapper.readValue(geoJsonStr, new TypeReference<Map<String, Object>>() {});
        } catch (IOException e) {
            // 如果生成GeoJSON或解析GeoJSON时失败,记录错误并抛出异常
            log.error("Failed to convert Geometry to GeoJSON Map", e);
            throw new IOException("Failed to convert Geometry to GeoJSON Map", e);
        }
    }

    /**
     * 测试方法
     */
    public static void main(String[] args) {
        // 示例 WKB 字符串
        String wkb = "0101000020E6100000B6F3FDD478195D40E7FBA9F1D2FD4340"; // 示例WKB字符串

        // 调用工具类方法
        Map<String, Object> geoJsonMap = null;
        try {
            geoJsonMap = convert(wkb, 6); // 转换为GeoJSON,保留6位小数
        } catch (Exception e) {
            log.error("Error converting WKB to GeoJSON", e);
            throw new RuntimeException(e);
        }
        // 打印结果
        log.info("GeoJSON Map: {}", geoJsonMap);
    }
}

通过这种方式,你可以将PostGIS中的WKB数据转换为GeoJSON格式的Map,方便在前端或其他系统中使用。

3、设计返回给前端的VO实体类

==将Map返回给前端,方便调用==

java 复制代码
@NoArgsConstructor
@AllArgsConstructor
@Data
public class LocationVO {
    @TableId
    private Integer id;
    private String name;
    // 将Map返回给前端,方便调用
    private Map<String, Object> geoJson;
}
4、service层调用
java 复制代码
public LocationVO findGeoJsonById(Long id) {
        Location geoJsonById = locationsMapper.findGeoJsonById(id);
        LocationVO locationVO = new LocationVO();
        BeanUtils.copyProperties(geoJsonById, locationVO);
        try {
            locationVO.setGeoJson(WKBToGeoJSONUtil.convert(geoJsonById.getGeom(), 6));
        }  catch (Exception e) {
            throw new RuntimeException(e);
        }
        return locationVO;
    }

返回结果

json 复制代码
{
    "id": 11,
    "name": "Location B",
    "geoJson": {
        "type": "MultiPolygon",
        "coordinates": [
            [
                [
                    [
                        115.737332,
                        28.640312
                    ],
                    [
                        115.73762,
                        28.640515
                    ],
                    [
                        115.73826,
                        28.639818
                    ],
                    [
                        115.737973,
                        28.639615
                    ],
                    [
                        115.737332,
                        28.640312
                    ]
                ]
            ]
        ]
    }
}
相关推荐
Dorian_Ov05 小时前
GeoServer发布pbf矢量切片和WCS服务以及ArcGIS api for js调用
gis
Moshow郑锴5 小时前
从 “瞎埋点” 到 “精准分析”:WebTagging 设计 + 页面埋点指南(附避坑清单)
前端
非凡ghost6 小时前
PixPin截图工具(支持截长图截动图) 中文绿色版
前端·javascript·后端
૮・ﻌ・6 小时前
Vue2(一):创建实例、插值表达式、Vue响应式特性、Vue指令、指令修饰符、计算属性
前端·javascript·vue.js
半生过往6 小时前
2025 前端动效实战指南:Vue Bits & React Bits 深度拆解(功能 / 复用 / 高频问题处理)
前端·vue.js·react.js
程序员包打听7 小时前
Vitest 4.0 重磅发布:Browser Mode 正式稳定,前端测试进入新纪元
前端
BumBle7 小时前
UniApp 多页面编译优化:编译时间从10分钟到1分钟
前端
星链引擎7 小时前
大语言模型的技术突破与稳定 API 生态的构建
前端
还是大剑师兰特7 小时前
TypeScript 面试题及详细答案 100题 (71-80)-- 模块与命名空间
前端·javascript·typescript