我有一个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)存储?
编辑:我还应该提到我使用了最新的一切,这通常似乎兼容:
Hibernate Spatial 4 tutorial建议我执行属性注释:
@Type(type="org.hibernate.spatial.GeometryType")
private Geometry centerPoint;
...但是当我这样做时,我得到this other error,当前注释会解析。
答案 0 :(得分:7)
解决方案似乎如下:
@Column
使用JPA注释将字段映射到所需列
@Type
用方言指定Hibernate映射。
@Column(columnDefinition = "Geometry", nullable = true)
@Type(type = "org.hibernate.spatial.GeometryType")
public Point centerPoint;
您可以在hibernate.cfg.xml文件中添加Hibernate属性以查看db请求并尝试使用基于文本的编辑器捕获字符串编码的问题,例如Notepad ++ with“UTF-8”/“ANSI”/“其他字符集“
<!--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的。只看我插入之前调用过的属性。
<?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
祝你好运!
答案 1 :(得分:3)
我将以下行添加到'application.properties'中来解决此问题:
spring.jpa.properties.hibernate.dialect=org.hibernate.spatial.dialect.postgis.PostgisDialect
答案 2 :(得分:1)
另请参阅,http://trac.osgeo.org/postgis/ticket/1830在Postgresql 9xx和Postgis 2xx出现时出现问题,导致使用postgres实用程序pgsql2shp时出现相同的“无效的endian标志”错误。可以修复删除库libpq.so的旧版本,因为Postgres更改了bytea的默认行为。
答案 3 :(得分:1)
在我的情况下,实体中的列定义为 @Column(name =“ geometry”) 私人几何图形;
并在数据库中以'geometry'类型输入(以避免休眠自动生成的bytea类型)
首先,我通过添加columnDefinition =“ geometry”解决了'遇到的无效字节序标志值',但是在此之后,休眠状态将通过“ Schema-validation:在表[einspekcija.lokacija_geometry]的列[geometry]中遇到错误的列类型而使模式验证失败];找到了[geometry(Types#OTHER)],但期望是[bytea(Types#VARBINARY)]“
添加spring.jpa.properties.hibernate.dialect = org.hibernate.spatial.dialect.postgis.PostgisDialect之后,它终于可以工作了。 ColumnDefinition现在也多余了
答案 4 :(得分:0)
在解决了给定的问题之后,这里有一些步骤可以帮助我解决问题。 首先,我应该提到我正在使用WildFly 17服务器,PostgreSQL 12和PostGIS 3.0.0。 现在,我认为在此问题中很重要的步骤:
在jboss-deployment-structure.xml
中创建META-INF
文件(如果您没有文件),并排除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
进行几何设计。
我希望我没有跳过任何重要的事情,而这些是必需的步骤。可能还有其他问题,但是尝试不同的解决方案已经花费了许多时间,而且我可能忘记了一些依赖项/属性。答案是根据个人经验得出的,因此可以随意评论,证明我错了或扩大答案。无论如何,我希望有人会觉得这个答案有用。