亲爱的 stackoverflow 读者,
我目前正在开发一个需要根据其坐标加载特定项目的应用程序。示例:我想要坐标 x 或其 15 公里以内的所有商店。
我一直在 Java EE 6 中构建此 Web 应用程序,并使用 Hibernate 3.3 将数据持久保存到我的 Postgres 数据库中。经过一番研究后,我发现 Hibernate-Spatial 可以实现我的目标。我安装了 Postgis 并运行了 Hibernate-Spatial。
我正在使用 Hibernate 3.3、Hibernate-Spatial 1.0、PostgreSQL 9.2 和 postgis-jdbc 1.3.3。
我创建了一个具有位置字段的实体:
@Column(columnDefinition = "Geometry", nullable = true)
@Type(type = "org.hibernatespatial.GeometryUserType")
private Point location;
最初我以为我可以创建一个圆并基本上查询位于圆中的每个点。但这似乎比我想象的要难。太难了,以至于我开始认为我使用 Hibernate-Spatial 的选择是错误的。
我的问题是,是否可以使用 Hibernate-Spatial 查询特定边界内的每个点(从那里开始的坐标 x 和 y km)。
我也对解决我的要求的其他可能性感兴趣。我一直在考虑以下可能性:
- 只需在 PostgreSQL 上使用 native 查询,将这些结果映射到实体并在应用程序的其他部分使用它们(基本上删除 Hibernate-Spatial 并使用 native 查询)。
- 切换到 Hibernate-Search 并使用 Lucene 来完成我的任务。
- 完全不同的东西
任何人都可以提供一个示例,说明我如何在 Hibernate-Spatial 中实现我的愿望,或者我如何以其他方式实现我的要求。
最佳答案
对于 PostgreSQL/PostGIS 方言,Hibernate Spatial 支持 dwithin
函数。
boolean dwithin(Geometry, Geometry, double)
- Returns true if the geometries are within the specified distance of one another
解释 Hibernate Spatial tutorial ,查询看起来像这样:
String wktCenterPoint = "POINT(10 15)"
Geometry centerPoint = wktToGeometry(wktCenterPoint);
...
Query query = em.createQuery("select e from Event e where dwithin(e.location, :centerPoint, 15) = true", Event.class);
...
这将返回距中心点 15 个单位范围内的所有事件。
但是 dwithin
中给出的距离将与基础数据集具有相同的单位,不一定是千米。如果数据集单位是米,则距离将被视为米。
如果数据集是 lat-lng,则距离将是度数。如果是这种情况,并且您的搜索距离很小(15 Km 很小),并且您处于低纬度,则可以将 Km 近似为 0.009。这将在赤道处为您提供一个完美的搜索圆,但是当您向北或向南移动时,该圆将变成一个长轴指向南北的椭圆。在 +/- 60 度纬度处,椭圆的高度将是宽度的两倍。显然不理想,但它可能适用于您的情况。
另一种方法是将您的数据集重新投影并存储在 PostgreSQL 中,作为以米为单位的投影数据集。如果在 map 上以大比例显示,这会扭曲您的数据,但您的搜索将按预期进行。
关于区域内点的 Hibernate-Spatial 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16333811/