
PostGIS ist eine Open Source-Software, die der relationalen PostgreSQL-Datenbank Unterstützung für geografische Funktionen hinzufügt.
In diesem kurzen Artikel wird die Verwendung in Java erläutert. Insbesondere die Aufgabe, geografische Objekte anhand ihrer Koordinaten zu finden.
PostGIS wurde bereits 2001 erstellt. Es ist eine gute kostenlose Lösung zum Speichern von Kartendaten in der Datenbank. In dem Artikel geht es jedoch nicht nur um ihn, sondern nur um einen Sonderfall - die bequeme Arbeit mit PostGIS mithilfe von JPA-Tools.
Abhängigkeiten
Folgende Bibliotheken sind für unsere Aufgabe wichtig:
- Ruhezustand 5.3.7
- Ruhezustand-räumlich - gleiche Version. Theoretisch können Sie die älteren verwenden. Ab dem fünften ist der räumliche Ruhezustand derselbe wie der Ruhezustand. Zuvor: Hibernate Spatial 1.1.x für Hibernate 3.6.x, Hibernate Spatial 1.0 für Hibernate 3.2.x - 3.5.x.
- postgresql 42.2.4. Diese Version wurde übernommen, da neuere die SSL-Anforderungen verschärften. Wählen Sie die Treiberversion, die der Datenbankversion entspricht.
Alles, was Sie für JPA benötigen, ist Spring oder ein Container.
Dialekte
Hibernate Spatial bietet geometrische
Abstraktionen für die Arbeit mit räumlichen Basen. Wie bei JPA interessiert uns in erster Näherung nicht, welche Datenbank auf dem Server verwendet wird.
Offiziell unterstützt von PostgresSQL, Oracle, MySQL, MS SQL Server, GeoDB (H2), DB2.
Features Support-Details . Muskel scheint wie ein Außenseiter. In Version 8 wird die Unterstützung von Geodaten jedoch erheblich
verbessert .
Wir verwenden Postgres. Sie müssen jedoch den Hibernate-Dialekt
"org.hibernate.spatial.dialect.postgis.PostgisDialect"
anstelle des standardmäßigen
"org.hibernate.spatial.dialect.postgis.PostgisDialect"
Dialekts angeben.
Es ist Zeit zu codieren
Eine Tabelle in PostGIS kann beliebige Felder enthalten. Nur Standard, einer von ihnen wird vom Typ Geometrie sein. Und es gibt Geografie (wird im Ruhezustand derzeit nicht unterstützt). Wenn Sie Java nicht beibringen, mit diesem Typ zu arbeiten, wird es als Blob oder String der Form "01010000207B7F0000188D594CC9B22541BC4E56674F2C5541" interpretiert.
Natürlich können Sie mit PostGis an einem reinen JBDC arbeiten.
Ein Beispiel . Dies erfordert jedoch eine separate sorgfältige Arbeit mit
org.postgis.PGgeometry
. Dies sind nicht die Klassen, um die es in dem Artikel geht. Und es wird keine Toleranz mehr geben.
Wir gehen zu JPA und erstellen eine einfache Klasse:
@Entity public class AdressBuilding implements Serializable { @Id private Integer id; private Point geom; ...
Die verbleibenden Felder werden weggelassen (ein geografisches Objekt kann alle Informationen speichern). Hier ist nichts Ungewöhnliches - die Standardentitätsklasse. Interessant ist nur ein Objekt der Klasse Point - ein Punkt des dreidimensionalen Raumes.
Im Folgenden werden Klassen aus dem Paket com.vividsolutions.jts.geom verwendet.
JTS ist zum De-facto-Standard für die Darstellung von Geodaten geworden. Es implementiert die von OpenGIS in den 90er Jahren erstellte Spezifikation Simple Feature Specification /
Simple Feature Access .
Klarstellung . Punkt erbt von der abstrakten Geometrieklasse. Es enthält die folgenden nicht statischen Felder:
protected Envelope envelope; protected final GeometryFactory factory; protected int SRID; private Object userData;
Umschlag ist der minimale Begrenzungsrahmen für diese Geometrie. Aber es kann in Form von Geometrie zurückkommen. Und dann haben Sie einen endlosen Versuch der Serialisierung.
SRID - Koordinatensystemnummer. Es gibt viele von ihnen. Die Hauptunterschiede: das Koordinatenformat (Meter, Grad ...), der Bezugspunkt und die Form der Erde (die Erde ist nicht rund). PostGis kennt viele Koordinatensysteme und kann diese transformieren.
Wie gesagt, wir haben einen Geometrietyp in der Datenbank. Der Einfachheit halber habe ich sofort die konkrete Punktklasse verwendet, da ich in dieser Tabelle nur Punktobjekte habe. PostGIS theoretisch kann jedoch mehrere Arten von Geometrie gleichzeitig speichern. Nur in jeder Geometrie wird der Typ angegeben:
"geometry":{"type":"MultiPolygon","coordinates":...
Laut StackOverflow verlangsamt die Verwendung mehrerer Geometrien in derselben Tabelle die Abfragen. Geometrien können auch verschachtelt werden. Typen:

Datenbankabfragen
Mit der Implementierung der Klasse herausgefunden. Jetzt ist es Zeit, sie von der Basis zu holen. Unsere Punkte sind Häuser bzw. deren Adressen. Sie können vertraute SQL-Abfragen stellen: Häuser nach ID, Anzahl, Anzahl der Großmütter abrufen ...
Wir sind jetzt an räumlichen Abfragen interessiert. Suchen Sie beispielsweise ein Haus nach Koordinaten. Die gewünschten Koordinaten x, y und + -Delta seien der gewünschte Suchbereich. Die Hauptabfragen in STS werden nach dem Verhältnis der Geometrien durchgeführt. Deshalb müssen wir es schaffen:
Coordinate c1 = new Coordinate(x - delta, y - delta); ... Coordinate[] coordinates = new Coordinate[]{c1, c2, c3, c4, c1}; GeometryFactory GEOMETRY_FACTORY = new GeometryFactory();
Wenn wir kein Koordinatensystem angeben, wird PostGis den Vergleich ablehnen. Sie kennen entweder Ihren
.getGeom().getSRID()
oder erhalten ihn von überall mit dem Code
.getGeom().getSRID()
.
Als nächstes senden wir eine Anfrage des Formulars:
"select a " + "from AdressBuilding a " + "where within(a.geom, :window) = true"
Eine Abfrage innerhalb bedeutet, zu überprüfen, ob sich die Geometrie in einer anderen befindet. Seien Sie nicht beunruhigt, wenn Ihre IDE sagt, dass es keine solche Anfrage in der JPA geben kann. Hibernate Spatial konvertiert es in:
where st_within(adressbuil0_.geom, ?)=true
Wobei
st_within
bereits eine PostGis-Funktion ist.
Es gibt verschiedene Möglichkeiten, um das gleiche Ergebnis zu erzielen - der Punkt fiel in ein Quadrat.
contains(:window, a.geom) / intersects(a.geom, :window)...

Eine detaillierte Beschreibung der Spezifikationen finden Sie
hier .
Nachwort
Wir haben die Punkte - jetzt machen Sie mit ihnen, was Sie wollen.
Ich habe den Fall einer kleinen Datenbank auf einem Server mit relativ viel RAM getestet. Wenn Sie maximal laden und Indizes vergessen, wird die Suchaufgabe im Prozessor ausgeführt.
Postgres hat viele verschiedene Indizes.
Und einige von ihnen helfen Postgis . Die Studie zeigte, dass nur GIST (?) Für
Punkte geeignet ist
CREATE INDEX [indexname] ON [tablename] USING GIST ( [geometryfield] );
Am häufigsten werden beim Importieren von Daten in PostGis Indizes automatisch erstellt ...
Erläuterungen und zusätzliche Informationen sind willkommen.
Handbuch verwendet:
Für den Winterschlaf 5Für den Winterschlaf 4