stereotypes etiquetas configurar componentes component anotacion spring hibernate postgresql spring-boot postgis

etiquetas - spring boot stereotypes



Asigne un campo de punto de geometrĂ­a PostGIS con Hibernar en Spring Boot (5)

En mi PostgreSQL 9.3 + PostGIS 2.1.5 tengo un PLACE tabla con una columna de coordinates de tipo Geometry(Point,26910) .

Quiero asignarlo a la entidad Place en mi aplicación web Spring Boot 1.1.9, que utiliza Hibernate 4.0.0 +. Place está disponible con un repositorio REST.

Desafortunadamente cuando GET http://localhost:8080/mywebapp/places , recibo esta extraña respuesta JSON :

{ "_embedded" : { "venues" : [ { "id" : 1, "coordinates" : { "envelope" : { "envelope" : { "envelope" : { "envelope" : { "envelope" : { "envelope" : { "envelope" : { "envelope" : { "envelope" : { "envelope" : { "envelope" : { "envelope" : { "envelope" : { "envelope" : { "envelope" : { "envelope" : { "envelope" : { "envelope" : { "envelope" : {

¡Y así indefinidamente ...! El registro de primavera no ayuda ..

Estoy trabajando con esta 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

En primer lugar, ¿está bien usar database-platform de database de database lugar de una database de database ? ¿Y tal vez tengo que usar la siguiente configuración en lugar de la anterior?

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

De todos modos mi entidad es algo como esto:

@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; }

Mi pom.xml contiene esta parte relevante:

<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>

Una configuración un poco extraña, la encontré en internet, es la que mejor funciona por ahora.

Espero que alguien me pueda ayudar con este misterio. :)


El problema no parece estar relacionado con PostgreSQL. Parece que su POJO tiene una referencia inversa, lo que significa que su asignador no sabe cómo manejarlo. Debe definir explícitamente las relaciones recursivas para que el asignador sepa cuándo detenerse. (Mi enlace de Goto -> http://vard-lokkur.blogspot.com/2010/10/json-jackson-to-rescue.html )



Finalmente, descubrí que mi configuración está bien y podría ser Jackson que no puede administrar el tipo de datos de Point correctamente. Así que personalicé su serialización y deserialización JSON:

  • agregue estas anotaciones a nuestro campo de coordinates :

    @JsonSerialize(using = PointToJsonSerializer.class) @JsonDeserialize(using = JsonToPointDeserializer.class)

  • crear tal serializador:

    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); } }

  • crear tal deserializador:

    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; } } }

Quizás también pueda usar este serializador y este deserializador , disponibles here .


Las soluciones anteriores me ayudaron a solucionar el problema. Lo simplifico para que otras personas puedan entenderlo.

Incluí esta biblioteca en mi pom.xml:

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

Este es el objeto POJO que usé. Luego pude hacer que la llamada REST funcione sin el error de la envolvente y los datos adecuados.

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; } }

Mi mesa tenía estas 2 columnas:

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


Si no desea agregar la anotación en todos los campos que usan un Punto, también puede usar @JsonComponent para registrar su JsonSerializer y JsonDeserializer .

@JsonComponent public class PointSerializer extends JsonSerializer<com.vividsolutions.jts.geom.Point>{ @Override public void serialize(com.vividsolutions.jts.geom.Point value, JsonGenerator gen, SerializerProvider provider) throws IOException { gen.writeStartObject(); gen.writeNumberField("lat", value.getY()); gen.writeNumberField("lon", value.getX()); gen.writeEndObject(); } }