You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Data JPA操作PostGIS插入地理数据报错求助

解决Spring Data JPA保存JTS几何对象到PostGIS的字节序错误

我用Leaflet绘制Point/MultiPolygon,通过Spring Data JPA存入带PostGIS的PostgreSQL。后端接收GeoJSON字符串,用自定义Jackson反序列化器转成org.locationtech.jts.geom.MultiPolygon和org.locationtech.jts.geom.Point,反序列化正常,但保存实体时触发Invalid endian flag value encountered错误。

自定义Jackson反序列化器

MultiPolygonDeserializer

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import org.locationtech.jts.geom.MultiPolygon;
import java.io.IOException;
import org.locationtech.jts.io.ParseException;
import org.locationtech.jts.io.geojson.GeoJsonReader;

public class MultiPolygonDeserializer extends JsonDeserializer<MultiPolygon> {

    @Override
    public MultiPolygon deserialize(JsonParser parser, DeserializationContext context) throws IOException {
        String geoJson = parser.getValueAsString();
        GeoJsonReader reader = new GeoJsonReader();
        try {
            return (MultiPolygon) reader.read(geoJson);
        } catch (ParseException e) {
            throw new IOException(e);
        }
    }
}

PointDeserializer

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import org.locationtech.jts.geom.Point;
import java.io.IOException;
import org.locationtech.jts.io.ParseException;
import org.locationtech.jts.io.geojson.GeoJsonReader;

public class PointDeserializer extends JsonDeserializer<Point> {

    @Override
    public Point deserialize(JsonParser parser, DeserializationContext context) throws IOException {
        String geoJson = parser.getValueAsString();
        GeoJsonReader reader = new GeoJsonReader();
        try {
            return (Point) reader.read(geoJson);
        } catch (ParseException e) {
            throw new IOException(e);
        }
    }
}

实体类Partner

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.pedro.geoPartners.util.MultiPolygonDeserializer;
import com.pedro.geoPartners.util.PointDeserializer;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import java.util.UUID;
import org.locationtech.jts.geom.MultiPolygon;
import org.locationtech.jts.geom.Point;

@Entity
public class Partner {

    @Id
    @GeneratedValue(strategy = GenerationType.UUID)
    private UUID id;

    private String tradingName;
    private String ownerName;
    private String document;

    @Column(columnDefinition = "geometry(Point,4326)")
    @JsonDeserialize(using = PointDeserializer.class)
    private Point address;

    @Column(columnDefinition = "geometry(MultiPolygon,4326)")
    @JsonDeserialize(using = MultiPolygonDeserializer.class)
    private MultiPolygon coverageArea;

    // Getters and Setters
    public UUID getId() { return id; }
    public void setId(UUID id) { this.id = id; }
    public String getTradingName() { return tradingName; }
    public void setTradingName(String tradingName) { this.tradingName = tradingName; }
    public String getOwnerName() { return ownerName; }
    public void setOwnerName(String ownerName) { this.ownerName = ownerName; }
    public String getDocument() { return document; }
    public void setDocument(String document) { this.document = document; }
    public Point getAddress() { return address; }
    public void setAddress(Point address) { this.address = address; }
    public MultiPolygon getCoverageArea() { return coverageArea; }
    public void setCoverageArea(MultiPolygon coverageArea) { this.coverageArea = coverageArea; }
}

错误日志

2023-03-04T17:51:39.152-03:00  WARN 116266 --- [nio-8080-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 0, SQLState: XX000
2023-03-04T17:51:39.152-03:00 ERROR 116266 --- [nio-8080-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper   : ERROR: Invalid endian flag value encountered.
2023-03-04T17:51:39.152-03:00  INFO 116266 --- [nio-8080-exec-1] o.h.e.j.b.internal.AbstractBatchImpl     : HHH000010: On release of batch it still contained JDBC statements
2023-03-04T17:51:39.157-03:00 ERROR 116266 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.springframework.orm.jpa.JpaSystemException: could not execute statement] with root cause

org.postgresql.util.PSQLException: ERROR: Invalid endian flag value encountered.
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2676) ~[postgresql-42.5.4.jar:42.5.4]
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2366) ~[postgresql-42.5.4.jar:42.5.4]
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:356) ~[postgresql-42.5.4.jar:42.5.4]
    at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:496) ~[postgresql-42.5.4.jar:42.5.4]...

配置信息

application.properties

spring.jpa.database=POSTGRESQL
spring.datasource.url=jdbc:postgresql://localhost:5432/GeoPartners?useTimeZone=true&serverTimezone=UTC&autoReconnect=true&useSSL=false
spring.datasource.username=postgres
spring.datasource.password=:)
spring.datasource.testWhileIdle=true
spring.datasource.validationQuery=SELECT 1
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.ImprovedNamingStrategy
spring.sql.init.mode=ALWAYS
spring.jpa.defer-datasource-initialization=true
hibernate.dialect=org.hibernate.spatial.dialect.postgis.PostgisDialect

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.0.3</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.pedro</groupId>
    <artifactId>geoPartners</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
    <name>geoPartners</name>
    <description>update of "JavaWebProject", implementing new features and Front-end</description>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-spatial</artifactId>
            <version>5.4.32.Final</version>
        </dependency>
        <dependency>
            <groupId>org.locationtech.jts.io</groupId>
            <artifactId>jts-io-common</artifactId>
            <version>1.19.0</version>
        </dependency>
        <dependency>
            <groupId>org.postgis</groupId>
            <artifactId>postgis-jdbc</artifactId>
            <version>1.3.3</version>
        </dependency>
    </dependencies>

    <repositories>
        <repository>
            <id>osgeo-alt</id>
            <url>https://repo.osgeo.org/repository/release/</url>
        </repository>
        <repository>
            <id>geomajas</id>
            <name>Geomajas Maven Repository</name>
            <url>http://maven.geomajas.org/(http://maven.geomajas.org/)</url>
        </repository>
    </repositories>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

解决方案

这个错误由依赖版本不兼容、Hibernate Spatial配置错误以及几何对象SRID缺失共同导致,按以下步骤修复:

  1. 调整依赖版本,移除冲突依赖

    • Spring Boot 3.x对应Hibernate 6.x,当前使用的Hibernate Spatial 5.4.x版本过低,存在兼容性问题。移除org.postgis:postgis-jdbc依赖,Hibernate Spatial会自动处理PostGIS的JDBC适配。
    • 修改hibernate-spatial依赖,使用Spring Boot 3.x兼容的版本,或直接让Spring Boot管理版本:
      <dependency>
          <groupId>org.hibernate.orm</groupId>
          <artifactId>hibernate-spatial</artifactId>
      </dependency>
      
    • 升级jts-io-common到2.0.0及以上版本,确保与Hibernate Spatial兼容:
      <dependency>
          <groupId>org.locationtech.jts.io</groupId>
          <artifactId>jts-io-common</artifactId>
          <version>2.0.0</version>
      </dependency>
      
  2. 修正Hibernate方言配置
    Spring Boot 3.x下需指定完整配置前缀,修改application.properties中的方言配置:

    spring.jpa.properties.hibernate.dialect=org.hibernate.spatial.dialect.postgis.PostgisDialect
    
  3. 为几何对象设置SRID
    反序列化后的JTS几何对象默认无SRID,需手动指定与数据库列一致的4326:

    // MultiPolygonDeserializer修改后
    @Override
    public MultiPolygon deserialize(JsonParser parser, DeserializationContext context) throws IOException {
        String geoJson = parser.getValueAsString();
        GeoJsonReader reader = new GeoJsonReader();
        try {
            MultiPolygon polygon = (MultiPolygon) reader.read(geoJson);
            polygon.setSRID(4326);
            return polygon;
        } catch (ParseException e) {
            throw new IOException(e);
        }
    }
    
    // PointDeserializer修改后
    @Override
    public Point deserialize(JsonParser parser, DeserializationContext context) throws IOException {
        String geoJson = parser.getValueAsString();
        GeoJsonReader reader = new GeoJsonReader();
        try {
            Point point = (Point) reader.read(geoJson);
            point.setSRID(4326);
            return point;
        } catch (ParseException e) {
            throw new IOException(e);
        }
    }
    
  4. 重建数据库表
    先删除已生成的相关表,临时设置spring.jpa.hibernate.ddl-auto=create重新生成表结构,之后改回update。

完成以上步骤后重启应用,即可正常保存几何对象到PostGIS数据库。

内容的提问来源于stack exchange,提问作者Pedro Augusto Almeida Duarte

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 00:57:08