
PostGIS是一种开源软件,它为PostgreSQL关系数据库增加了对地理特征的支持。
这篇简短的文章将讨论它在Java中的用法。 特别是通过地理坐标查找地理对象的任务。
PostGIS创建于2001年。 这是一个很好的免费解决方案,用于将地图数据存储在数据库中。 但是本文并不完全是关于他的,而是仅涉及一种特殊情况-使用JPA工具与PostGIS进行便捷的工作。
依存关系
以下库对于我们的任务很重要:
- 休眠5.3.7
- 休眠空间 -相同版本。 从理论上讲,您可以使用较旧的。 从第五位开始,休眠空间与休眠相同。 以前:Hibernate 3.6.x适用于Hibernate Spatial 1.1.x,Hibernate 3.2.x适用于Hibernate Spatial 1.0-3.5.x。
- PostgreSQL 42.2.4。 之所以采用此版本,是因为较新的版本严格了SSL要求。 选择与数据库版本匹配的驱动程序版本。
好吧,JPA所需的全部是Spring或一个容器。
方言
Hibernate Spatial提供了用于处理空间基础的几何
抽象 。 与在JPA中一样,作为第一近似,我们对服务器上使用哪个数据库不感兴趣。
由PostgresSQL,Oracle,MySQL,MS SQLServer,GeoDB(H2),DB2正式支持。
功能支持详细信息 。 肌肉看起来像是局外人。 但是在版本8中,空间数据支持
得到了显着改善 。
我们使用Postgres。 但是您需要指定一个Hibernate方言
"org.hibernate.spatial.dialect.postgis.PostgisDialect"
而不是标准的后希腊语。
该写代码了
PostGIS中的表格可以包含任何字段。 仅作为标准,其中之一将是几何类型。 并且有地理位置(Hibernate现在不支持)。 如果您不教Java使用这种类型,它将被解释为形式为“ 01010000207B7F0000188D594CC9B22541BC4E56674F2C5541”的Blob或String。
当然,您可以在纯JBDC上使用PostGis。
一个例子 。 但这需要对
org.postgis.PGgeometry
进行单独的艰苦工作。 这些不是本文将要讨论的类。 而且将不再有宽容。
我们转到JPA并创建一个简单的类:
@Entity public class AdressBuilding implements Serializable { @Id private Integer id; private Point geom; ...
其余字段将被忽略(地理对象可以存储任何信息)。 这里没有什么不寻常的-标准实体类。 只有Point类的对象才是有趣的-三维空间的点。
在下文中,将使用com.vividsolutions.jts.geom包中的类。
JTS已成为表示地理空间数据的事实上的标准。 它实现了90年代由OpenGIS创建的简单功能规范/
简单功能访问规范。
澄清 。 Point继承于抽象的Geometry类。 它包含以下非静态字段:
protected Envelope envelope; protected final GeometryFactory factory; protected int SRID; private Object userData;
信封是此几何的最小边界框。 但是它可以几何形式返回。 然后,您将无休止地尝试序列化。
SRID-坐标系统编号。 有很多。 主要区别在于:坐标格式(米,度...),参考点和地球的形状(地球不是圆形的)。 PostGis知道许多坐标系并可以对其进行转换。
就像我说的,数据库中有一个几何类型。 为了方便起见,我立即使用了具体的Point类,因为在此表中,我只有Point对象。 但是PostGIS理论上可以一次存储几种类型的几何。 仅在每个几何图形中指示其类型:
"geometry":{"type":"MultiPolygon","coordinates":...
根据StackOverflow,在同一张表中使用多个几何会降低查询速度。 几何形状也可以嵌套。 类型:

数据库查询
随着类的执行弄清楚了。 现在是时候从基础上获取他们了。 我们的要点是房屋,或更确切地说是地址。 您可以进行熟悉的SQL查询:按ID,编号,祖母数量获取房屋...
现在,我们对空间查询感兴趣。 例如,通过坐标查找房屋。 令所需的坐标x,y和+ -delta为所需的搜索区域。 STS中的主要查询是根据几何比例进行的。 因此,我们需要创建它:
Coordinate c1 = new Coordinate(x - delta, y - delta); ... Coordinate[] coordinates = new Coordinate[]{c1, c2, c3, c4, c1}; GeometryFactory GEOMETRY_FACTORY = new GeometryFactory();
如果我们未指定坐标系,则PostGis将拒绝对其进行比较。 您要么知道系统代码,要么使用代码
.getGeom().getSRID()
从任何地方获取它。
接下来,我们发送以下形式的请求:
"select a " + "from AdressBuilding a " + "where within(a.geom, :window) = true"
内部查询意味着检查几何是否在另一个内部。 如果您的IDE指出JPA中没有这样的请求,请不要惊慌。 Hibernate Spatial将其转换为:
where st_within(adressbuil0_.geom, ?)=true
其中
st_within
已经是PostGis函数。
如何获得相同的结果,有几种选择-点落成一个正方形。
contains(:window, a.geom) / intersects(a.geom, :window)...

规格的详细说明在
这里 。
后记
我们掌握了要点-现在可以随心所欲。
我在具有相对大量RAM的服务器上测试了小型数据库的情况。 如果加载到最大而忘记了索引,则搜索任务将运行到处理器中。
Postgres有许多不同的索引。
其中一些帮助Postgis 。 研究表明,只有GIST(?)适用于
积分 CREATE INDEX [indexname] ON [tablename] USING GIST ( [geometryfield] );
但是最常见的是,当您将数据导入PostGis时,索引会自动创建...
欢迎澄清和其他信息。
使用手册:
对于冬眠5对于休眠4