2016-05-31 13 views
2

Ich arbeite mit Hibernate 5.1.0 in einer Java-Anwendung. Ich verbinde beide mit einer Postgres 9.5 mit Postgis Erweiterungen und Oracle Datenbanken. Ich brauche alle Geometrien in der Datenbank zu finden, die mit einer gegebenen Geometrie schneiden, auf die ich anwenden einen Puffer, wie zum Beispiel:Hibernate und Postgres: Funktion st_buffer (Bytea, numerisch) ist nicht eindeutig

Query query = session 
      .createQuery("select b from Block b where intersects(b.geom, buffer(:geometry, " + bufferDistance + ")) = " 
        + UtilsHelper.getTrueBooleanValue(em)); 
query.setParameter("geometry", geom); 
List<Block> blocks = query.list(); 

, die in Oracle arbeitet, aber in Postgres werde ich den Fehler:

Caused by: org.postgresql.util.PSQLException: ERROR: function st_buffer(bytea, numeric) is not unique 
Hint: Could not choose a best candidate function. You might need to add explicit type casts. 
Position: 243 
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2270) 

Dies macht Sinn, da es nicht in der Lage sein wird, die zwischen einem der folgenden Funktionen zu wählen:

geometry ST_Buffer(geometry g1, float radius_of_buffer); 
geography ST_Buffer(geography g1, float radius_of_buffer_in_meters); 

Die UtilsHelper.getTrueBooleanValue(em) wird nur den richtigen booleschen Wert abhängig vom Entitätsmanager erhalten, dh 0/1 für Oracle und wahr/falsch für Postgres.

Eine naheliegende Lösung wäre, eine der Funktionen zu löschen. Abgesehen davon, gibt es eine Möglichkeit, das zu beheben?

Antwort

2

Ich will nicht zu wissen viel über Hibernate behaupten, aber es scheint, dass eine einfache Lösung zu explicitly cast ist die bytea mit CAST(:geometry AS geometry) und Modernisierung der Rest Abfrage eine „ST_“ Präfix hinzufügen, die mit neueren Versionen PostGIS verwendet wird .

Noch wichtiger ist, sollten Sie nie eine Abfrage mit der Form schreiben:

SELECT b 
FROM Block b 
WHERE ST_Intersects(b.geom, ST_Buffer(CAST(:geometry AS geometry), :bufferDistance)) = TRUE; 

Unter Verwendung eines Puffers eine Region auszuwählen ist langsamer und unvollkommener als die Verwendung einer entfernungsabhängigen ST_DWithin function die Geometrien zu finden, die in einem sind Entfernung. ST_DWithin kann auch einen räumlichen Index verwenden, falls verfügbar. Und ein boolescher Operator braucht den = + UtilsHelper.getTrueBooleanValue(em)-Teil nicht zu haben (d. H. TRUE = TRUE ist TRUE). Einfach entfernen.

Versuchen Sie, eine Funktion zu schreiben, die mehr wie folgt aussieht:

SELECT b 
FROM Block b 
WHERE ST_Dwithin(b.geom, CAST(:geometry AS geometry), :distance); 

(unter Verwendung von zwei Parametern :geometry und :distance)

+0

Vielen Dank für Ihre Antwort, Mike T. Ich versuche es mit, dass funktioniert BESETZUNG. Jedenfalls wird das wohl nur für Postgres und nicht für Oracle gut sein. Wie gesagt, ich brauche das mit beiden DBs zu arbeiten. Genau deshalb setze ich auf Hibernate, um die tatsächliche Abfrage zu erzeugen, sei es mit ST_Buffer oder irgendeinem ST_-Präfix für Postgres oder dem SDO-Äquivalent in Oracle. – krause

+0

@krause wieder Ich bin nicht vertraut mit Hibernate, aber Oracle hat [SDO_WITHIN_DISTANCE] (https://docs.oracle.com/cd/B19306_01/appdev.102/b14255/sdo_operat.htm#i77653) was ST_DWithin entspricht oben erwähnt. –