PostGIS Geometry saving: “Invalid endian flag value encountered.”
我有一个Spring Roo Hibernate项目,该项目需要从客户端应用程序输入JTS知名文本(WKT)字符串,然后将其转换为JTS Geometry对象,然后尝试将其写入PostGIS数据库。我在JDBC连接和类型方面遇到了一些问题,但这些问题似乎已通过以下方式解决:
1 2 | @Column(columnDefinition ="Geometry", nullable = true) private Geometry centerPoint; |
转换完成:
1 | Geometry geom = new WKTReader(new GeometryFactory(new PrecisionModel(), 4326)).read(source); |
但是现在,当Hibernate尝试将我的Geometry对象写入数据库时??,出现错误:
1 2 | 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. |
似乎很明显,该错误与二进制表示形式有关,该表示形式可能是作为具有某些字节序的众所周知的二进制(WKB)生成的。但是,由于Hibernate隐藏了所有持久性,所以我无法真正判断事情的发展方向。
我已经为这个"几何"问题战斗了好几天了,关于这些错误的信息很少,所以有人有什么聪明的主意吗?我可以在某个地方(Hibernate或PostGIS)指定字节顺序,还是以其他格式(WKT)存储?
编辑:我还应该提到我正在使用最新的所有东西,通常看起来是兼容的:
- Spring 3.1.1,Roo 1.2.1
- Hibernate3.6.9
- hibernate空间4.0-M1
- 捷报1.12
- PostgreSQL 9.1
- postgis-jdbc 1.5.3(不是最新版本,但建议用于hibernate空间,从源代码编译)
- postgis-jdbc 2.0.1(现在尝试将其与PostgreSQL安装的版本匹配,同样的问题)
Hibernate Spatial 4教程建议我将属性标注做为:
1 2 | @Type(type="org.hibernate.spatial.GeometryType") private Geometry centerPoint; |
...但是当我这样做时,我得到了另一个错误,当前注释可以解决。
我将以下行添加到" application.properties"中来解决此问题:
1 | spring.jpa.properties.hibernate.dialect=org.hibernate.spatial.dialect.postgis.PostgisDialect |
解决方案似乎如下:
1 2 3 | @Column(columnDefinition ="Geometry", nullable = true) @Type(type ="org.hibernate.spatial.GeometryType") public Point centerPoint; |
您可以在hibernate.cfg.xml文件中添加Hibernate属性,以查看db请求,并尝试使用基于文本的编辑器(例如带有" UTF-8" /" ANSI" /"的记事本)捕获字符串编码的问题。其他字符集"
1 2 3 4 | <!--hibernate.cfg.xml --> <property name="show_sql">true</property> <property name="format_sql">true</property> <property name="use_sql_comments">true</property> |
要添加hibernate属性,您将具有一个hibernate.cfg.xml文件,其中包含以下内容。不要复制/粘贴它,因为它是面向MySQL的。只需看看我在前面插入的属性的位置即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <?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文件内添加程序包特定的属性:
1 2 | log4j.logger.org.hibernate.SQL=DEBUG log4j.logger.org.hibernate.type=TRACE |
祝你好运!
pilladooo的解决方案适用于Spring Boot 2.0.3,hibernate/空间5.2.17,Final,Postgres 9.5。
在我的情况下,
实体中的列定义为
@Column(name =" geometry")
专用几何体;
并在数据库中以'geometry'类型输入(以避免hibernate自动生成的bytea类型)
首先,我通过添加columnDefinition =" geometry"解决了'遇到的无效字节序标志值',但是此后,hibernate状态将通过" Schema-validation:在表[my_shema.my_geometry_table]的列[geometry]中遇到错误的列类型而使模式验证失败];找到了[geometry(Types#OTHER)],但期望是[bytea(Types#VARBINARY)]"
添加spring.jpa.properties.hibernate.dialect = org.hibernate.spatial.dialect.postgis.PostgisDialect之后,它终于可以工作了。 ColumnDefinition现在也是多余的
另请参见,http://trac.osgeo.org/postgis/ticket/1830在Postgresql 9xx和Postgis 2xx出现时出现了一个问题,使用postgres时导致了相同的"无效字节序标志"错误实用程序pgsql2shp。可以通过删除库libpq.so的旧版本来修复该问题,这是由于Postgres更改了bytea的默认行为。
在解决了给定的问题之后,这里有一些步骤可以帮助我解决问题。
首先,我应该提到我正在使用WildFly 17服务器,PostgreSQL 12和PostGIS 3.0.0。
现在,我认为在此问题中很重要的步骤:
在
1 2 3 4 5 6 7 | <jboss-deployment-structure> <deployment> <exclusions> <module name="org.hibernate" /> </exclusions> </deployment> </jboss-deployment-structure> |
在您的
1 2 3 4 5 | <dependency> <groupId>org.hibernate</groupId> hibernate-core</artifactId> <version>5.4.12.Final</version> </dependency> |
和
1 2 3 4 5 | <dependency> <groupId>org.hibernate</groupId> hibernate-spatial</artifactId> <version>5.4.12.Final</version> </dependency> |
请确保hibernate核心和hibernate空间具有相同的版本(使用您喜欢的任何版本)。
您的
1 | <property name="hibernate.dialect" value="org.hibernate.spatial.dialect.postgis.PostgisDialect"/> |
最后,我认为这不是很重要,但是我在Java中将
我希望我没有跳过任何重要的事情,而这些是必需的步骤。可能还有其他问题,但是尝试不同的解决方案已经花费了许多时间,而且我可能忘记了一些依赖项/属性。答案是根据个人经验得出的,因此可以随意发表评论,以证明我错了或扩大答案。无论如何,我希望有人会觉得这个答案有用。