2014-12-23 2 views
15

In meinem PostgreSQL 9.3 + PostGIS 2.1.5 habe ich eine Tabelle PLACE mit einer Spalte coordinates des Typs Geometry(Point,26910).Ordnen Sie ein PostGIS Geometrie Punktfeld mit Hibernate auf Spring Boot

Ich möchte es auf Place Einheit in meiner Spring Boot 1.1.9 Web-Anwendung, die Hibernate 4.0.0 + verwendet. Place ist mit einem REST-Repository verfügbar.

Leider wenn ich GET http://localhost:8080/mywebapp/places Ich erhalte dieses seltsame JSON Antwort:

{ 

    "_embedded" : { 

    "venues" : [ { 

     "id" : 1, 

     "coordinates" : { 

     "envelope" : { 

      "envelope" : { 

      "envelope" : { 

       "envelope" : { 

       "envelope" : { 

        "envelope" : { 

        "envelope" : { 

         "envelope" : { 

         "envelope" : { 

          "envelope" : { 

          "envelope" : { 

           "envelope" : { 

           "envelope" : { 

            "envelope" : { 

            "envelope" : { 

             "envelope" : { 

             "envelope" : { 

              "envelope" : { 

              "envelope" : { 

und so weiter indefinetely ...! Frühlings-Protokoll hilft nicht ..

ich mit dieser Arbeit application.properties:

spring.jpa.database-platform=org.hibernate.spatial.dialect.postgis.PostgisDialect 
spring.jpa.show-sql=false 
spring.jpa.hibernate.ddl-auto=update 

spring.datasource.url=jdbc:postgresql://192.168.1.123/mywebapp 
spring.datasource.username=postgres 
spring.datasource.password=mypwd 
spring.datasource.driverClassName=org.postgresql.Driver 

Zunächst einmal ist es in Ordnung, database-platform zu verwenden, anstatt database? Und vielleicht muss ich folgende Einstellungen anstelle der oben genannten verwenden?

spring.datasource.url=jdbc:postgresql_postGIS://192.168.1.123/mywebapp 
spring.datasource.driverClassName=org.postgis.DriverWrapper 

Auf jeden Fall mein Unternehmen so etwas wie dieses:

enthält
@Entity 
public class Place { 
    @Id 
    public int id; 
    @Column(columnDefinition="Geometry") 
    @Type(type="org.hibernate.spatial.GeometryType") //"org.hibernatespatial.GeometryUserType" seems to be for older versions of Hibernate Spatial 
    public com.vividsolutions.jts.geom.Point coordinates; 
} 

Mein pom.xml diese relevanten Teil:

<dependency> 
    <groupId>org.postgresql</groupId> 
    <artifactId>postgresql</artifactId> 
    <version>9.3-1102-jdbc41</version> 
</dependency> 
<dependency> 
    <groupId>org.hibernate</groupId> 
    <artifactId>hibernate-spatial</artifactId> 
    <version>4.3</version><!-- compatible with Hibernate 4.3.x --> 
    <exclusions> 
     <exclusion> 
      <artifactId>postgresql</artifactId> 
      <groupId>postgresql</groupId> 
     </exclusion> 
    </exclusions> 
</dependency> 

Ein bisschen seltsam Konfiguration, ich habe es im Internet zu finden, Es ist das, das am besten für jetzt funktioniert.

Ich hoffe, dass mir jemand mit diesem Geheimnis helfen konnte. :)

Antwort

15

Schließlich entdeckte ich, dass meine Konfiguration in Ordnung ist und vielleicht Jackson sein, die nicht Point Datentyp korrekt verwalten. So maßgeschneiderte ich seine JSON Serialisierung und Deserialisierung:

  • fügen Sie diese Anmerkungen zu unserem coordinates Feld:

    @JsonSerialize(using = PointToJsonSerializer.class) 
    @JsonDeserialize(using = JsonToPointDeserializer.class) 
    
  • schaffen solche Serializer:

    import java.io.IOException; 
    import com.fasterxml.jackson.core.JsonGenerator; 
    import com.fasterxml.jackson.core.JsonProcessingException; 
    import com.fasterxml.jackson.databind.JsonSerializer; 
    import com.fasterxml.jackson.databind.SerializerProvider; 
    import com.vividsolutions.jts.geom.Point; 
    
    public class PointToJsonSerializer extends JsonSerializer<Point> { 
    
        @Override 
        public void serialize(Point value, JsonGenerator jgen, 
          SerializerProvider provider) throws IOException, 
          JsonProcessingException { 
    
         String jsonValue = "null"; 
         try 
         { 
          if(value != null) {    
           double lat = value.getY(); 
           double lon = value.getX(); 
           jsonValue = String.format("POINT (%s %s)", lat, lon); 
          } 
         } 
         catch(Exception e) {} 
    
         jgen.writeString(jsonValue); 
        } 
    
    } 
    
  • schaffen solche Deserializer:

    import java.io.IOException; 
    import com.fasterxml.jackson.core.JsonParser; 
    import com.fasterxml.jackson.core.JsonProcessingException; 
    import com.fasterxml.jackson.databind.DeserializationContext; 
    import com.fasterxml.jackson.databind.JsonDeserializer; 
    import com.vividsolutions.jts.geom.Coordinate; 
    import com.vividsolutions.jts.geom.GeometryFactory; 
    import com.vividsolutions.jts.geom.Point; 
    import com.vividsolutions.jts.geom.PrecisionModel; 
    
    public class JsonToPointDeserializer extends JsonDeserializer<Point> { 
    
        private final static GeometryFactory geometryFactory = new GeometryFactory(new PrecisionModel(), 26910); 
    
        @Override 
        public Point deserialize(JsonParser jp, DeserializationContext ctxt) 
          throws IOException, JsonProcessingException { 
    
         try { 
          String text = jp.getText(); 
          if(text == null || text.length() <= 0) 
           return null; 
    
          String[] coordinates = text.replaceFirst("POINT ?\\(", "").replaceFirst("\\)", "").split(" "); 
          double lat = Double.parseDouble(coordinates[0]); 
          double lon = Double.parseDouble(coordinates[1]); 
    
          Point point = geometryFactory.createPoint(new Coordinate(lat, lon)); 
          return point; 
         } 
         catch(Exception e){ 
          return null; 
         } 
        } 
    
    } 
    

Vielleicht können Sie auch this serializer verwenden und this deserializer, erhältlich here.

+0

Ich stelle fest, dass die Ausgabe Breite und Länge von Ihrem Serializer ausgetauscht werden. ist das erwartet? Dieser Code erklärt 'double lat = value.getY();' und 'double lon = value.getX();' danke – randytan

+0

@randytan Ich habe diesen Code vor langer Zeit verwendet, aber ich erinnere mich, dass Breite und Länge wo in der richtigen Reihenfolge. Wo siehst du sie getauscht? – bluish

+0

Wenn Sie 'POINT (AB)' senden und 'sys.out' an Ihre Variable' jsonValue = String.format ("POINT (% s% s)", lat, lon); 'Sie können sehen, dass es tatsächlich geschrieben wird 'PUNKT (BA)'. Ich tausche einfach den Code 'value.getY()' und 'value.getX()', um die Position zu korrigieren. Vielen Dank – randytan

0

Das Problem scheint nicht mit PostgreSQL zusammenhängen. Anscheinend hat Ihr POJO eine Rückwärtsreferenz, was bedeutet, dass Ihr Mapper nicht weiß, wie er damit umgehen soll. Sie müssen die rekursiven Beziehungen explizit definieren, damit der Mapper weiß, wann er anhalten muss. (My Goto Link ->http://vard-lokkur.blogspot.com/2010/10/json-jackson-to-rescue.html)

+0

keinen Hinweis auf eine andere Einheit zu haben, dann ist dies nicht das Problem. Trotzdem danke! – bluish

1

Die oben genannten Lösungen haben mir geholfen, das Problem zu beheben. Ich vereinfache es, damit andere Leute es verstehen können.

enthalten ich diese Bibliothek in meinem pom.xml:

<dependency> 
    <groupId>com.bedatadriven</groupId> 
    <artifactId>jackson-datatype-jts</artifactId> 
    <version>2.2</version> 
</dependency> 

Dies ist das POJO Objekt I verwendet. Dann konnte ich den REST-Aufruf ohne den Hüllkurvenfehler und die richtigen Koordinaten ausführen.

import com.bedatadriven.jackson.datatype.jts.serialization.GeometryDeserializer; 
import com.bedatadriven.jackson.datatype.jts.serialization.GeometrySerializer; 
import com.fasterxml.jackson.databind.annotation.JsonDeserialize; 
import com.fasterxml.jackson.databind.annotation.JsonSerialize; 
import com.vividsolutions.jts.geom.Geometry; 

@Entity 
@Table(name = "boundary") 
public class Boundary { 

    private int id; 
    private Geometry geomertry; 

    @Id 
    public int getId() { 
     return ogc_fid; 
    } 

    public void setId(int id) { 
     this.id = id; 
    } 

    @JsonSerialize(using = GeometrySerializer.class) 
    @JsonDeserialize(using = GeometryDeserializer.class) 
    @Column(name = "geometry", columnDefinition = "Geometry") 
    public Geometry getGeomertry() { 
     return geomertry; 
    } 

    public void setGeomertry(Geometry geomertry) { 
     this.geomertry = geomertry; 
    } 
} 

Meine Tabelle werden diese 2 Spalten hatte:

id  | integer    
geometry | geometry(Geometry,4326) |