【问题标题】:PostGIS Geometry saving: "Invalid endian flag value encountered."PostGIS 几何保存:“遇到无效的字节序标志值。”
【发布时间】:2012-08-31 12:17:24
【问题描述】:

我有一个 Spring Roo + Hibernate 项目,它从客户端应用程序获取 JTS 知名文本 (WKT) 字符串输入,将其转换为 JTS Geometry 对象,然后尝试将其写入 PostGIS 数据库。我对the JDBC connection and types 有一些问题,但这些问题似乎已通过以下方式解决:

@Column(columnDefinition = "Geometry", nullable = true) 
private Geometry centerPoint;

转换确实如此:

Geometry geom = new WKTReader(new GeometryFactory(new PrecisionModel(), 4326)).read(source);

但是现在当 Hibernate 尝试将我的 Geometry 对象写入数据库时​​,我得到一个错误:

2012-08-31 21:44:14,096 [tomcat-http--18] ERROR org.hibernate.util.JDBCExceptionReporter - Batch entry 0 insert into land_use (center_point, version, id) values ('<stream of 1152 bytes>', '0', '1') was aborted.  Call getNextException to see the cause.
2012-08-31 21:44:14,096 [tomcat-http--18] ERROR org.hibernate.util.JDBCExceptionReporter - ERROR: Invalid endian flag value encountered.

似乎很明显,该错误与二进制表示有关,它可能是生成为带有一些endianness 的众所周知的二进制 (WKB)。然而,由于 Hibernate 隐藏了所有的持久性,我真的无法判断事情的发展方向。

我已经与这个几何问题作斗争好几天了,关于这些错误的信息很少,所以有人有什么好主意吗?我可以在某处(Hibernate 或 PostGIS)指定字节顺序,或者以不同的格式(WKT)存储吗?

编辑:我还应该提到,我使用的是最新的,通常似乎是兼容的:

  • Spring 3.1.1,Roo 1.2.1
  • 休眠 3.6.9
  • 休眠空间 4.0-M1
  • jts 1.12
  • PostgreSQL 9.1
  • postgis-jdbc 1.5.3(不是最新的,而是recommended for hibernate-spatial,编译自源码)
  • postgis-jdbc 2.0.1(刚刚尝试了这个来匹配安装PostgreSQL的版本,同样的问题)

Hibernate Spatial 4 tutorial 建议我将属性注释为:

@Type(type="org.hibernate.spatial.GeometryType")
private Geometry centerPoint;

...但是当我这样做时,我得到this other error,当前注释已解决。

【问题讨论】:

  • 您好,我关注您的 OpenGIS 问题 :) 您是否尝试过两次方法 @Type(type="org.hibernate.spatial.GeometryType") 注释加上 JPA​​ 注释 @Column(columnDefinition = "Geometry", nullable = true) 关联到同一字段。
  • 其他库也有类似geodb issue n°5 的问题。我建议你应该试试 postgis 测试套件,看看你是否遇到同样的问题。这看起来像是字节序字符编码的问题,好的,但有时事情不像他们第一眼看到的那样。您是否尝试使用 getNextException() 方法获得更多信息,或者您的日志的第二行就是您能得到的所有信息?
  • 我发现以下java hibernate postgis tutorial 建议按照我所说的去做。它是法语的,好的,但是如果您需要翻译,我可以提供帮助(我是法语,哈哈)。在建议的教程中,它简要解释了我在第一条评论中提到的每个注释的作用。看来您需要按照我的建议进行设置。

标签: spring hibernate geometry endianness jts


【解决方案1】:

我解决了这个问题,添加到 'application.properties' 这一行:

spring.jpa.properties.hibernate.dialect=org.hibernate.spatial.dialect.postgis.PostgisDialect

【讨论】:

  • 它也为我解决了这个问题。我在application.properties 中有hibernate.dialect=... 而不是spring.jpa.properties.hibernate.dialect=...。列的定义是这样的:@Column(columnDefinition = "GEOGRAPHY(POINT)") private com.vividsolutions.jts.geom.Point location;
【解决方案2】:

解决方案似乎如下:
@Column 使用 JPA 注释将字段映射到所需列
@Type 使用方言指定 Hibernate 映射。

@Column(columnDefinition = "Geometry", nullable = true) 
@Type(type = "org.hibernate.spatial.GeometryType")
public Point centerPoint;

您可以在 hibernate.cfg.xml 文件中添加 Hibernate 属性以查看 db 请求并尝试使用基于文本的编辑器(例如带有“UTF-8”/“ANSI”/”的 Notepad++ 来捕获字符串编码问题其他字符集”

<!--hibernate.cfg.xml -->
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<property name="use_sql_comments">true</property>

要添加休眠属性,您将拥有一个包含以下内容的 hibernate.cfg.xml 文件。不要复制/粘贴它,因为它是面向 MySQL 的。看看我在哪里插入了我之前调用的属性。

 <?xml version="1.0" encoding="utf-8"?>
 <!DOCTYPE hibernate-configuration PUBLIC
 "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
 "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
 <hibernate-configuration>
      <session-factory>
           <property name="hibernate.bytecode.use_reflection_optimizer">true</property>
           <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
           <property name="hibernate.connection.password">db-password</property>
           <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/db-name</property>
           <property name="hibernate.connection.username">db-username</property>
           <property name="hibernate.default_entity_mode">pojo</property>
           <property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
           <property name="hibernate.format_sql">true</property>
           <property name="hibernate.search.autoregister_listeners">false</property>
           **<property name="hibernate.show_sql">true</property>**
           <property name="hibernate.use_sql_comments">false</property>

           <mapping ressource="...." />
           <!-- other hbm.xml mappings below... -->

      </session-factory>
 </hibernate-configuration>

另一种记录所有 sql 的方法是在 log4j.properties 文件中添加特定于包的属性:

log4j.logger.org.hibernate.SQL=DEBUG
log4j.logger.org.hibernate.type=TRACE

祝你好运!

【讨论】:

  • 这肯定解决了字节序问题,所以谢谢。然而,可以预见的是,我现在有另一个内部错误:Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Error while committing the transaction。堆栈跟踪没有帮助,让休眠配置标签工作比预期的更困难。这对您来说是显而易见的,还是需要一个新问题?
  • 你好,也许正在寻找任何@Transactional 的东西。我今天没有足够的时间(国际象棋活动)。也许我明天可以帮你。我将添加一个完整的休眠配置,以便您查看它。祝你好运!
  • 嗯。也许您的数据库模型不允许您要存储在数据库中的 PostGIS 对象涉及的任何字段为空值。如果您使用断点运行项目并点击F6 以逐步进入您的java 程序,您将看到何时抛出异常。您可以点击F5 进入您想要检查的任何方法。查看使用 eclipse 和您正在使用的容器(Tomcat、JBoss、GlassFish 等)配置远程调试。
  • 另外,未来的读者会注意到那些 hibernate.cfg.xml 标签应该在 hibernate 命名空间中,即 hibernate.show_sql 等。对于 Roo 项目,他们进入 persistence.xml,并且需要将日志记录至少打开到 DEBUG 级别。
  • 请注意,以上解决方案适用于休眠 4,如果您使用休眠 5,请查看piladooo 的回答或我的解释
【解决方案3】:

piladooo 的解决方案适用于 spring boot 2.0.3、hibernate/spatial 5.2.17.Final、Postgres 9.5。

在我的例子中,实体中的列定义为 @Column(name = "几何") 私有几何几何;

并在数据库中作为“几何”类型(以避免休眠自动生成的 bytea 类型)

首先,我通过添加 columnDefinition = "geometry" 解决了“遇到的无效字节序标志值”,但之后休眠将通过“模式验证:在表 [my_shema.my_geometry_table ]; 找到 [geometry (Types#OTHER)],但期待 [bytea (Types#VARBINARY)]"

在添加 spring.jpa.properties.hibernate.dialect=org.hibernate.spatial.dialect.postgis.PostgisDialect 之后它终于起作用了。 ColumnDefinition 现在也是多余的

【讨论】:

    【解决方案4】:

    另请参阅,http://trac.osgeo.org/postgis/ticket/1830 在 Postgresql 9xx 和 Postgis 2xx 出现的时候出现了一个问题,在使用 postgres 实用程序 pgsql2shp 时导致了相同的“无效的字节序标志”错误。可以通过删除旧版本的库 libpq.so 来修复它,因为这是由于 Postgres 更改了 bytea 的默认行为。

    【讨论】:

      【解决方案5】:

      在解决给定问题后,这里有一些步骤可以帮助我解决它。 首先我应该提到我正在使用 WildFly 17 服务器、PostgreSQL 12 和 PostGIS 3.0.0。 现在我认为对这个问题很重要的步骤:

      META-INF 中创建jboss-deployment-structure.xml 文件(如果你没有的话),并排除WildFly 自带的休眠

      <jboss-deployment-structure>
          <deployment>
              <exclusions>
                  <module name="org.hibernate" />
              </exclusions>
          </deployment>
      </jboss-deployment-structure>
      

      在你的 pom.xml 添加依赖项

      <dependency>
          <groupId>org.hibernate</groupId>
              <artifactId>hibernate-core</artifactId>
          <version>5.4.12.Final</version>
      </dependency>
      

      <dependency>
          <groupId>org.hibernate</groupId>
              <artifactId>hibernate-spatial</artifactId>
          <version>5.4.12.Final</version>
      </dependency>
      

      确保休眠核心和休眠空间具有相同的版本(使用您喜欢的任何版本)。

      你的persistence.xml 应该有财产

      <property name="hibernate.dialect" value="org.hibernate.spatial.dialect.postgis.PostgisDialect"/>
      

      最后,我认为这不是很重要,但我在 Java 中使用 org.locationtech.jts 表示几何。

      我希望我没有跳过任何重要的步骤,并且这些是必需的步骤。可能还有其他东西,但是尝试不同的解决方案已经过去了很多小时,而且我可能忘记包含一些依赖项/属性。答案基于个人经验,因此请随时发表评论,证明我错了或扩大答案。无论如何,我希望有人会发现这个答案很有用。

      【讨论】:

        【解决方案6】:

        我可以使用以下配置。 我正在使用 Spring Boot 2.5.1、PostGIS 和 hibernate-spatial 5.4.32.Final。 几个关键点:

        1. 我使用的 Point 类是 org.locationtech.jts.geom.Point
        2. 您不需要特殊注释。这是我的实体类。

        实体:

        @Enity public class Vehicle {
        
            @Id
            @GeneratedValue(strategy = GenerationType.IDENTITY)
            private Long id;
        
            private String name;    
            
            private Point location;
        }
        

        我也在application.properties中使用

        spring.jpa.database-platform=org.hibernate.spatial.dialect.postgis.PostgisPG95Dialect
        

        然后在服务类中,我可以通过如下调用将对象保存到数据库中。

        public Vehicle createVehicle(String name, Double longitude, Double latitude) {
            GeometryFactory geometryFactory = new GeometryFactory(new PrecisionModel(), 4326);
                var point = geometryFactory.createPoint(new Coordinate(longitude, latitude));
            
                var vehicle = new Vehicle(name, point);      
                return vehicleRepository.save(vehicle);
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-05-09
          • 2013-12-03
          • 2017-04-19
          • 1970-01-01
          • 1970-01-01
          • 2017-06-22
          • 1970-01-01
          相关资源
          最近更新 更多