【问题标题】:Use Point type with PostgreSQL and JPA/Hibernate在 PostgreSQL 和 JPA/Hibernate 中使用 Point 类型
【发布时间】:2014-04-06 20:19:48
【问题描述】:

有没有办法将 Point 列映射到 Java 实体字段?

我尝试过 Hibernate Spatial 4.0,但似乎它不适用于没有 PostGIS 的纯 PostgreSQL。这是点字段定义:

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 的几何类型。但我只想使用简单的点。

【问题讨论】:

    标签: java hibernate postgresql jpa


    【解决方案1】:

    您应该尝试将您的数据库中的类型设置为几何,我也没有设法用 mySQL 做到这一点。 几何图形对点也很有效..

    【讨论】:

    • 这是什么意思?我在 PostgreSQL 9.3 中看不到几何数据类型
    • 也许 @foxTox 表示 PostGIS Geometry 数据类型。实际上 Hibernate Spatial 不支持 Geography 类型(参见 How do I map a 'Geography(POINT, 4326)' type?)。
    • 我可以将点保存为几何类型,但在查看数据库中的数据时无法读取。有没有办法解决这个问题?
    【解决方案2】:

    由于我不完全确定这个问题,让我先尝试解释一下:

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

    一些研究让我得出结论,上面提到的hibernate支持的标准方言根本不支持PostgreSQL点类型。所以你可能想提供你自己的UserType。查看 hibernate 手册中的 Custom types 或博客中的 Understanding and writing Hibernate custom user types 示例。

    【讨论】:

    • 谢谢希勒。我不限于com.vividsolutions.jts.geom.Point。如果有另一个对象可以映射 PostgreSQL point 类型,那就没问题了。如果我必须实现UserType,我想知道使用 2 个double 字段来代替 lat 和 long 是否会更好。但我担心我会丢失一些可用于point 类型的有用功能。
    • a) 意思是说(现在编辑),无论您尝试映射到哪种 Java 类型,hibernate 提供的方言都不支持 PostgreSQL“点”类型。 b) 如果一开始就没有理由使用 PostgreSQL“point”类型,可以尝试使用 JPA 2.1 AttributeConverter(需要 hibernate >= 4.3)。
    • 好奇你决定变蓝的方向,即使我迟到了 3 年
    • 我认为这个答案最接近原始问题的要求。缺少的一点是应该使用 Postgres 驱动程序中的org.postgresql.geometric.PGpoint(驱动程序可以在本机准备好的语句中对其进行序列化)而不是com.vividsolutions.jts.geom.Point。然后按照此答案的建议为 Hibernate 实现 UserType 或查看 this answer 以获取复制粘贴示例。
    【解决方案3】:

    我可以通过我在项目中使用过的@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;
    ...
    }
    

    【讨论】:

    • 那么当我们需要多边形和线串时,您的解决方案是什么?
    • @AliReza19330 对于这些结构,我更喜欢找到一种方法开始使用vividsolutions lib,也许现在它可以在hibernate5上正常工作,抱歉我还没有处理它。
    【解决方案4】:

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

    您遇到的错误是因为您没有在数据库上安装任何与 Hibernate 相关的内容。抱怨的是 postgres,即:

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

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

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

    所以基本上你正在尝试使用不受支持的配置。

    PostgreSQL 并没有像 Oracle 那样提供任何人曾想过的所有可能的数据类型。所以当 Hibernate 说“我想要一个'几何' PostgreSQL 只是说“什么是几何?”PostgreSQL 是非常可扩展的,所以 PostGIS 人就是这样做的——他们构建了一个扩展。任何人都可以安装它或完全没有它运行。唯一的问题它的原因是有人期望它在开箱即用的数据库中,而不是作为一个附加组件。

    我想您可能会尝试对 PostgreSQL 数据类型进行逆向工程并将它们编译到您的数据库中。 Geometry 是 PostGIS 的主要超类,至少在 Java 中是这样,它在数据库中看起来是一样的。我只是不明白为什么你会在没有人支持的情况下设置配置。

    @bluish 这有帮助吗?

    【讨论】:

    • 虽然你给出了一个很好的答案,但 OP 要求没有 PostGIS 的解决方案。
    • 如果 OP 想使用 postgis 方言,它只能在数据库中安装 postgis 的情况下可靠地工作。必须摆脱方言。
    【解决方案5】:

    此链接将对您有所帮助 链接https://www.compose.com/articles/geofile-everything-in-the-radius-with-postgis/

    除此之外,distanceWithin() 函数以度数表示距离,您必须将其转换为地理,但休眠空间不支持,因此还有另一种方法可以通过根据您的要求提供十进制距离来实现此目的。链接下面提到小数点。

    用于十进制转换 链接https://en.wikipedia.org/wiki/Decimal_degrees

    【讨论】:

    • 链接会随着时间的推移而消失。当您共享的链接发生这种情况时,您的答案将指向损坏的链接。我建议您至少可以为链接写一个摘要。
    猜你喜欢
    • 2019-05-19
    • 2011-02-18
    • 2018-06-02
    • 1970-01-01
    • 2013-09-08
    • 2016-10-12
    • 2023-03-20
    • 2020-03-19
    • 2016-06-26
    相关资源
    最近更新 更多