使用Point类型与PostgreSQL和JPA/Hibernate

21

有没有一种方法将Point列映射到Java实体字段?

我尝试了Hibernate Spatial 4.0,但似乎它不能与纯PostgreSQL一起使用,需要安装PostGIS。这是点字段的定义:

import com.vividsolutions.jts.geom.Point;
...
@Column(columnDefinition = "point")
@Type(type = "org.hibernate.spatial.GeometryType")
private Point location;

在 persistence.xml 中的方言:

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

当我尝试保存此实体时,会抛出异常:

org.postgresql.util.PSQLException: Unknown type geometry.
at org.postgresql.jdbc2.AbstractJdbc2Statement.setPGobject(AbstractJdbc2Statement.java:1603)
at org.postgresql.jdbc2.AbstractJdbc2Statement.setObject(AbstractJdbc2Statement.java:1795)
at org.postgresql.jdbc3g.AbstractJdbc3gStatement.setObject(AbstractJdbc3gStatement.java:37)
at org.postgresql.jdbc4.AbstractJdbc4Statement.setObject(AbstractJdbc4Statement.java:46)
at org.hibernate.spatial.dialect.AbstractJTSGeometryValueBinder.bind(AbstractJTSGeometryValueBinder.java:48)
at org.hibernate.spatial.dialect.AbstractJTSGeometryValueBinder.bind(AbstractJTSGeometryValueBinder.java:39)
at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:280)
at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:275)
at org.hibernate.type.AbstractSingleColumnStandardBasicType.nullSafeSet(AbstractSingleColumnStandardBasicType.java:57)

看起来它试图将值持久化为PostGIS的几何类型。但我只想使用简单的点。

5个回答

9

在您的数据库中安装PostGIS扩展。

您遇到的错误是因为您没有在数据库中安装Hibernate可以关联的任何内容。这是postgres在抱怨,即:

org.postgresql.util.PSQLException:未知类型几何。

您的注释和配置表明它们依赖于PostGIS:

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

基本上,您正在尝试使用不受支持的配置。
PostgreSQL没有像Oracle那样提供所有可能想到的数据类型。所以当Hibernate说“我需要一个'geometry'”时,PostgreSQL只会问:“什么是几何图形?”PostgreSQL非常可扩展,这就是PostGIS的人所做的-他们建立了一个扩展程序。任何人都可以安装它或完全不使用它。它唯一引起的问题是当有人期望它在开箱即用的数据库中而不是作为附加组件时。
我想您可以尝试反向工程PostgreSQL数据类型并将其编译到数据库中。Geometry至少在Java中是PostGIS的主超类,在数据库中看起来也是如此。我只是不明白为什么您要设置一个配置,因为您永远不会得到任何人的支持。
@bluish这有帮助吗?

1
尽管您给出了一个很好的答案,但 OP 要求不使用 PostGIS 的解决方案。 - bluish
如果 OP 想要使用 postgis 方言,那么只有在数据库中安装了 postgis 才能可靠地工作。必须摆脱方言。 - Andrew Wolfe

7
我可以通过使用@ Embedded Entity(它不依赖于数据库类型!)来提供一种更通用的方式,我在项目中使用过。
以下是示例:
创建包含LAT和LONG的某些表的SQL查询片段:
CREATE TABLE some_table (
  lat    NUMBER(..., ...),
  long   NUMBER(..., ...),
...
);

可嵌入的点实体:
@Embeddable
public class Point {
    private BigDecimal x;
    private BigDecimal y;
 ...
}

您的自定义实体:

@Entity
@Table(name = "some_table")
public class SomeEntity {
    @Embedded
    @AttributeOverrides({
            @AttributeOverride(name = "lat", column = @Column(name = "x")),
            @AttributeOverride(name = "long", column = @Column(name = "y"))
    })
    private Point point;
...
}

那么当我们需要多边形和线串时,你有什么解决方案? - Ali Abazari
@AliReza19330 对于这种结构,我更喜欢找到一种使用vividsolutions库的方法,也许现在它已经可以很好地与hibernate5配合使用了,抱歉我还没有接触过它。 - Pianov

6

由于我不完全确定问题,先让我尝试换个说法:

您想将一个具有类型为com.vividsolutions.jts.geom.Point字段的实体映射到PostgreSQL数据库列类型为“point”(参见postgreSQL几何类型),使用hibernate,并限制自己使用“标准”(即hibernate提供的)方言PostgreSQLDialect

一些研究导致我得出结论,上述提到的hibernate支持的标准方言根本不支持PostgreSQL点类型。因此,您可能需要提供自己的UserType。请查看hibernate手册中的自定义类型理解和编写Hibernate自定义用户类型的博客示例。


1
谢谢Hille。我不限于使用com.vividsolutions.jts.geom.Point。如果有另一个对象可以映射PostgreSQL的point类型,那就可以了。如果我必须实现一个UserType,我想知道是否最好使用2个double字段来表示纬度和经度。但我担心会失去一些可用于point类型的有用函数。 - bluish
a) 我的意思是(现已编辑),无论您尝试映射到什么Java类型,Hibernate提供的方言都不支持PostgreSQL的“point”类型。 b) 如果没有使用PostgreSQL的“point”类型的原因,可以尝试使用JPA 2.1 AttributeConverter(需要hibernate> = 4.3)。 - Hille
好奇你决定朝着蓝色的方向前进,即使我晚了3年才加入派对。 - daniel9x
我认为这个答案最接近原问题的要求。缺失的部分是应该使用Postgres驱动程序中的org.postgresql.geometric.PGpoint(驱动程序可以在准备好的语句中本地序列化它),而不是com.vividsolutions.jts.geom.Point。然后按照此答案建议实现Hibernate的UserType,或者参见此答案以获取复制粘贴示例。 - Yaroslav Admin

6

你应该尝试将数据库中的类型设为几何类型,我也没能在MySQL上实现它。 几何类型对于点来说是很好用的。


1
你的意思是什么?我在我的PostgreSQL 9.3中看不到Geometry数据类型。 - bluish
也许@foxTox指的是PostGIS的“Geometry”数据类型。实际上,Hibernate Spatial不支持“Geography”类型(请参见如何映射“Geography(POINT,4326)”类型?)。 - bluish
我能够将点保存为几何类型,但查看数据库中的数据时无法读取。有什么解决方法吗? - daniel9x

0

链接会随着时间的推移而失效。当你分享的链接失效时,你的回答也会指向无法访问的链接。我建议你至少写一个链接摘要。 - Lajos Arpad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接